From 9cab36727e4921b17255b1f7373bb68ba759b35f Mon Sep 17 00:00:00 2001
From: BluemediaGER <oliver@traber-info.de>
Date: Mon, 20 Feb 2023 19:23:16 +0100
Subject: [PATCH 1/2] Update README.md

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index b453f73..9ca0341 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # 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>

From 7a0edc13766a347187eb9177dfbccd3b8210ff50 Mon Sep 17 00:00:00 2001
From: BluemediaGER <oliver@traber-info.de>
Date: Mon, 20 Feb 2023 22:50:54 +0100
Subject: [PATCH 2/2] Add custom saml-post-form

---
 README.md                                 |  3 +-
 src/types/context.ts                      | 10 ++++
 src/types/samlPostData.ts                 |  5 ++
 src/views/saml-post-form/index.ftl        |  6 +++
 src/views/saml-post-form/index.ts         |  7 +++
 src/views/saml-post-form/index.vue        | 65 +++++++++++++++++++++++
 src/views/webauthn-authenticate/index.vue |  2 +-
 webpack.config.js                         |  2 +-
 8 files changed, 97 insertions(+), 3 deletions(-)
 create mode 100644 src/types/samlPostData.ts
 create mode 100644 src/views/saml-post-form/index.ftl
 create mode 100644 src/views/saml-post-form/index.ts
 create mode 100644 src/views/saml-post-form/index.vue

diff --git a/README.md b/README.md
index 9ca0341..5c73e9d 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,8 @@ keycloak-modern-login is a Keycloak login theme that's build using Tailwind CSS,
 
 ![](docs/login-form.jpg)
 
-![](docs/login-webauthn.jpg)  
+![](docs/login-webauthn.jpg)
+
 </details>
 
 ## State of this project
diff --git a/src/types/context.ts b/src/types/context.ts
index f33a8a3..1a7c3a8 100644
--- a/src/types/context.ts
+++ b/src/types/context.ts
@@ -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 = {
diff --git a/src/types/samlPostData.ts b/src/types/samlPostData.ts
new file mode 100644
index 0000000..6bc70c3
--- /dev/null
+++ b/src/types/samlPostData.ts
@@ -0,0 +1,5 @@
+export type SAMLPostData = {
+    SAMLRequest?: string,
+    SAMLResponse?: string,
+    relayState?: string,
+}
\ No newline at end of file
diff --git a/src/views/saml-post-form/index.ftl b/src/views/saml-post-form/index.ftl
new file mode 100644
index 0000000..21397e4
--- /dev/null
+++ b/src/views/saml-post-form/index.ftl
@@ -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>
diff --git a/src/views/saml-post-form/index.ts b/src/views/saml-post-form/index.ts
new file mode 100644
index 0000000..9344ee4
--- /dev/null
+++ b/src/views/saml-post-form/index.ts
@@ -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");
+}
diff --git a/src/views/saml-post-form/index.vue b/src/views/saml-post-form/index.vue
new file mode 100644
index 0000000..e5ea71e
--- /dev/null
+++ b/src/views/saml-post-form/index.vue
@@ -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>
diff --git a/src/views/webauthn-authenticate/index.vue b/src/views/webauthn-authenticate/index.vue
index e433d12..ed6a2e8 100644
--- a/src/views/webauthn-authenticate/index.vue
+++ b/src/views/webauthn-authenticate/index.vue
@@ -86,7 +86,7 @@ import type { KcContextBase } from "~/types/context";
 import { base64url } from "rfc4648";
 
 export default defineComponent({
-  name: "Login",
+  name: "WebAuthnAuthenticate",
   components: {
     Layout,
     ErrorBox,
diff --git a/webpack.config.js b/webpack.config.js
index 5807125..ba34e35 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -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";