Compare commits

...

2 commits

Author SHA1 Message Date
Oliver Traber 7a0edc1376
Add custom saml-post-form 2023-02-20 22:50:54 +01:00
Oliver Traber 9cab36727e
Update README.md 2023-02-20 19:23:16 +01:00
8 changed files with 98 additions and 4 deletions

View file

@ -1,13 +1,14 @@
# A modern Keycloak login theme
keycloak-modern-login is a Keycloak login theme that's build using Vue.js 3 and Typescript. It is easily extensible and bypasses the complexity of FreeMarker templates.
keycloak-modern-login is a Keycloak login theme that's build using Tailwind CSS, Vue.js 3 and Typescript. It is easily extensible and bypasses the complexity of FreeMarker templates.
<details>
<summary>Screenshots</summary>
![](docs/login-form.jpg)
![](docs/login-webauthn.jpg)
![](docs/login-webauthn.jpg)
</details>
## State of this project

View file

@ -325,6 +325,16 @@ export declare namespace KcContextBase {
attributesByName: Record<string, Attribute>;
};
};
export type SAMLPostForm = Common & {
pageId: "saml-post-form.ftl"
samlPost: {
url: string;
SAMLRequest?: string;
SAMLResponse?: string;
relayState?: string;
}
};
}
export type Attribute = {

View file

@ -0,0 +1,5 @@
export type SAMLPostData = {
SAMLRequest?: string,
SAMLResponse?: string,
relayState?: string,
}

View file

@ -0,0 +1,6 @@
<#import "baselayout.ftl" as layout>
<@layout.baseLayout pageId="saml-post-form.ftl" ; section>
<#if section = "scripts">
<script typo="module" src="${url.resourcesPath}/js/saml-post-form.js"></script>
</#if>
</@layout.baseLayout>

View file

@ -0,0 +1,7 @@
import { createApp } from "vue";
import index from "./index.vue";
if ((window as any).kcContext) {
const app = createApp(index);
app.mount("#app");
}

View file

@ -0,0 +1,65 @@
<template>
<layout>
<div class="flex justify-center justify-items-center">
<svg class="h-15 w-15 animate-spin" preserveAspectRatio="xMidYMid">
<circle cx="50%" cy="50%" r="35" fill="none" stroke="#374151" stroke-width="10" stroke-dasharray="164 56"/>
</svg>
</div>
<h1 class="mt-4 text-xl text-center text-gray-700">Redirecting...</h1>
</layout>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import Layout from "~/components/Layout.vue";
import type { KcContextBase } from "~/types/context";
import type { SAMLPostData } from "~/types/samlPostData"
export default defineComponent({
name: "SamlPostForm",
components: {
Layout,
},
data() {
return {
context: (window as any).kcContext as KcContextBase.SAMLPostForm,
};
},
mounted: function () {
const postData: SAMLPostData = {
SAMLRequest: this.context.samlPost.SAMLRequest,
SAMLResponse: this.context.samlPost.SAMLResponse,
relayState: this.context.samlPost.relayState,
};
this.formPost(this.context.samlPost.url, postData);
},
methods: {
formPost(url: string, data: object) {
const form = document.createElement("form");
form.method = "post";
form.action = url;
for (const key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
if (data[key] === undefined) {
continue;
}
const hiddenField = document.createElement("input");
hiddenField.type = "hidden";
hiddenField.name = key;
hiddenField.value = data[key];
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
},
},
});
</script>
<style>
@tailwind base;
@tailwind components;
@tailwind utilities;
</style>

View file

@ -86,7 +86,7 @@ import type { KcContextBase } from "~/types/context";
import { base64url } from "rfc4648";
export default defineComponent({
name: "Login",
name: "WebAuthnAuthenticate",
components: {
Layout,
ErrorBox,

View file

@ -5,7 +5,7 @@ const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const THEME_NAME = "modern-login";
const customPages = ["login", "webauthn-authenticate"];
const customPages = ["login", "webauthn-authenticate", "saml-post-form"];
module.exports = function (env, argv) {
const isDevelopment = argv.mode !== "production";