From 8155ffe0cefb0aadb1f13365e682e9ae8d000a4a Mon Sep 17 00:00:00 2001 From: phil Date: Sat, 1 Feb 2025 11:24:48 +0100 Subject: [PATCH 01/19] Cosmetic --- public/styles.css | 10 +++++++--- src/App.vue | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/public/styles.css b/public/styles.css index 17d7c4c..2f458f4 100644 --- a/public/styles.css +++ b/public/styles.css @@ -2,11 +2,15 @@ body { font-family: Arial, Helvetica, sans-serif; background-color: floralwhite; margin: 0; + font-family: system-ui; } h1 { text-align: center; background-color: #f786867d; margin: 0 0 0.2em 0; + box-shadow: 0px 0.2em 0.2em #f786867d; + text-shadow: 0 0 2px #00000080; + font-weight: 200; } p { margin: 0.2em; @@ -184,8 +188,8 @@ hr { width: fit-content; align-items: center; margin: 5px auto; - box-shadow: 0px 0px 10px #90c3ee; - background-color: #90c3ee; + box-shadow: 0px 0px 10px #90c3eeA0; + background-color: #90c3eeA0; border-radius: 8px; } @@ -201,7 +205,7 @@ hr { color: darkred; } -.from-keycloak-vue { +.token-info { margin: 0 1em; } diff --git a/src/App.vue b/src/App.vue index fc161f9..aed43d5 100644 --- a/src/App.vue +++ b/src/App.vue @@ -59,6 +59,7 @@ async function get_resource(id: string) { {{ keycloak.idTokenParsed?.oidc_provider }} +
@@ -80,9 +81,8 @@ async function get_resource(id: string) {
{{ msg }}
-
+

-

idToken

From 0782d9d12d23339c927685002f068feb92318e6d Mon Sep 17 00:00:00 2001 From: phil Date: Sat, 1 Feb 2025 11:30:26 +0100 Subject: [PATCH 02/19] Cosmetic --- public/styles.css | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/public/styles.css b/public/styles.css index 2f458f4..da5e989 100644 --- a/public/styles.css +++ b/public/styles.css @@ -24,6 +24,9 @@ hr { .center { text-align: center; } +.error { + color: darkred; +} .content { width: 100%; display: flex; @@ -201,10 +204,6 @@ hr { text-align: center; } -.error { - color: darkred; -} - .token-info { margin: 0 1em; } From a0b391b4173cdea154b2d271a9409ec630e7a925 Mon Sep 17 00:00:00 2001 From: phil Date: Sat, 1 Feb 2025 16:15:52 +0100 Subject: [PATCH 03/19] Cosmetic --- public/styles.css | 10 +++++++++- src/App.vue | 12 ++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/public/styles.css b/public/styles.css index da5e989..a532917 100644 --- a/public/styles.css +++ b/public/styles.css @@ -104,10 +104,18 @@ hr { .hasResponseStatus.status-503 { background-color: #ffA88050; } -.role { +.role, .scope { padding: 3px 6px; + border-radius: 6px; + margin: 3px; +} +.role { background-color: #44228840; } +.scope { + background-color: #8888FF80; +} + /* For home */ diff --git a/src/App.vue b/src/App.vue index aed43d5..d05a079 100644 --- a/src/App.vue +++ b/src/App.vue @@ -49,14 +49,18 @@ async function get_resource(id: string) {

Hey, {{ keycloak.idTokenParsed?.name }}

{{ keycloak.idTokenParsed?.email }}
-
- Roles: - {{ +
+ Roles for oidc-test: + {{ role }}
Provider: - {{ keycloak.idTokenParsed?.oidc_provider }} + {{ keycloak.idTokenParsed.oidc_provider }} +
+
+ Scopes: + {{ scope }}
From f7d2279d1995a885b846f7f8bab634aafb9d2d53 Mon Sep 17 00:00:00 2001 From: phil Date: Fri, 7 Feb 2025 04:58:47 +0100 Subject: [PATCH 04/19] Cleanup style --- public/styles.css | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/public/styles.css b/public/styles.css index a532917..3f9679d 100644 --- a/public/styles.css +++ b/public/styles.css @@ -3,9 +3,9 @@ body { background-color: floralwhite; margin: 0; font-family: system-ui; + text-align: center; } h1 { - text-align: center; background-color: #f786867d; margin: 0 0 0.2em 0; box-shadow: 0px 0.2em 0.2em #f786867d; @@ -58,7 +58,6 @@ hr { border: 2px solid darkkhaki; padding: 3px 6px; text-decoration: none; - text-align: center; color: black; } .user-info a.logout:hover { @@ -73,7 +72,6 @@ hr { margin: 0; } .debug-auth p { - text-align: center; border-bottom: 1px solid black; } .debug-auth ul { @@ -104,14 +102,17 @@ hr { .hasResponseStatus.status-503 { background-color: #ffA88050; } + .role, .scope { padding: 3px 6px; - border-radius: 6px; margin: 3px; + border-radius: 6px; } + .role { background-color: #44228840; } + .scope { background-color: #8888FF80; } @@ -120,7 +121,6 @@ hr { /* For home */ .login-box { - text-align: center; background-color: antiquewhite; margin: 0.5em auto; width: fit-content; @@ -147,7 +147,6 @@ hr { max-height: 2em; } .providers .provider .link div { - text-align: center; background-color: #f7c7867d; border-radius: 8px; padding: 6px; @@ -162,13 +161,11 @@ hr { } .providers .error { padding: 3px 6px; - text-align: center; font-weight: bold; flex: 1 1 auto; } .content .links-to-check { display: flex; - text-align: center; justify-content: center; gap: 0.5em; flex-flow: wrap; From 24dcb7a9db40a6b26644bccb4265033dc2415e1e Mon Sep 17 00:00:00 2001 From: phil Date: Fri, 7 Feb 2025 05:00:27 +0100 Subject: [PATCH 05/19] Add and automatic check links to resources --- src/App.vue | 32 ++++++++++++++++++++++++++++---- src/main.ts | 22 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/App.vue b/src/App.vue index d05a079..3122449 100644 --- a/src/App.vue +++ b/src/App.vue @@ -18,6 +18,10 @@ async function doAuthenticatedRequest() { const response = await authServer.get('/oidc-test-web') } +function getResourceUrl(url: string): string { + return settings.resourceServerUrl + "/" + url +} + function logout() { keycloak.logoutFn && keycloak.logoutFn() } @@ -34,7 +38,10 @@ async function get_resource(id: string) { msg.value = "" } ).catch( - err => msg.value = err + err => { + resource.value = [] + msg.value = `${err.message} (${err.response.statusText}): ${err.response.data["detail"]}` + } ) } @@ -84,7 +91,24 @@ async function get_resource(id: string) {
-
{{ msg }}
+
{{ msg }}
+

@@ -98,14 +122,14 @@ async function get_resource(id: string) {

access token

-
{{ key }}
+
{{ key }}
{{ value }}

refresh token

-
{{ key }}
+
{{ key }}
{{ value }}
diff --git a/src/main.ts b/src/main.ts index 427388e..b771875 100644 --- a/src/main.ts +++ b/src/main.ts @@ -44,6 +44,7 @@ axios.get("settings.json").then().then( }, onReady(keycloak: Keycloak) { initializeTokenInterceptor(keycloak) + checkPerms('links-to-check') }, }) app.mount("#app") @@ -72,4 +73,25 @@ function initializeTokenInterceptor(keycloak: Keycloak) { }) } +async function checkHref(elem: HTMLLinkElement) { + await resourceServer.get(elem.href).then( + resp => { + elem.classList.add("hasResponseStatus") + elem.classList.add("status-" + resp.status) + elem.title = "Response code: " + resp.status + " - " + resp.statusText + }).catch(err => { + elem.classList.add("hasResponseStatus") + elem.classList.add("status-" + err.response.status) + elem.title = "Response code: " + err.response.status + " - " + err.response.statusText + }) +} + +function checkPerms(className: string) { + var rootElems = document.getElementsByClassName(className) + Array.from(rootElems).forEach(elem => + Array.from(elem.children).forEach(elem => checkHref(elem)) + ) +} + + const app = createApp(App) From 553e85a5d562c1cc70888669b7ab405f3d7f8093 Mon Sep 17 00:00:00 2001 From: phil Date: Fri, 7 Feb 2025 13:20:30 +0100 Subject: [PATCH 06/19] Fix network error message for resource server --- src/App.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/App.vue b/src/App.vue index 3122449..2a4f53e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -40,7 +40,11 @@ async function get_resource(id: string) { ).catch( err => { resource.value = [] - msg.value = `${err.message} (${err.response.statusText}): ${err.response.data["detail"]}` + if (err.response) { + msg.value = `${err.message} (${err.response.statusText}): ${err.response.data["detail"]}` + } else { + msg.value = `${err.message} (cannot reach the resource server)` + } } ) } From 88423b26ddc52b83e84a424eb59ee4570120bf01 Mon Sep 17 00:00:00 2001 From: phil Date: Fri, 7 Feb 2025 16:45:27 +0100 Subject: [PATCH 07/19] Follow changes of oidc-test: move all resources to json; use buttons --- public/styles.css | 9 ++---- src/App.vue | 74 +++++++++++++++++++++++++---------------------- src/main.ts | 4 ++- 3 files changed, 44 insertions(+), 43 deletions(-) diff --git a/public/styles.css b/public/styles.css index 3f9679d..cc7abeb 100644 --- a/public/styles.css +++ b/public/styles.css @@ -170,11 +170,12 @@ hr { gap: 0.5em; flex-flow: wrap; } -.content .links-to-check a { +.content .links-to-check button { color: black; padding: 5px 10px; text-decoration: none; border-radius: 8px; + border: none; } .token { @@ -182,12 +183,6 @@ hr { font-family: monospace; } -.actions { - display: flex; - justify-content: center; - gap: 0.5em; -} - .resource { padding: 0.5em; display: flex; diff --git a/src/App.vue b/src/App.vue index 2a4f53e..7fd21b1 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,5 +1,5 @@ + + diff --git a/src/main.ts b/src/main.ts index f4bc87d..b9bfc24 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,4 @@ -import { createApp } from 'vue' +import { createApp, ref } from 'vue' import Keycloak from "keycloak-js" import VueKeycloakJs from '@dsb-norge/vue-keycloak-js' import axios, { type AxiosInstance } from 'axios' @@ -15,6 +15,14 @@ interface Settings { tokenSandbox: boolean } +export interface Resource { + name: string +} + +export interface Resources { + [name: string]: Resource +} + export let settings: Settings export let authServer: AxiosInstance export let resourceServer: AxiosInstance @@ -72,8 +80,8 @@ function initializeTokenInterceptor(keycloak: Keycloak) { }) } -async function checkHref(elem: HTMLLinkElement) { - const url = elem.getAttribute("resource-id") +export async function checkResource(elem: HTMLLinkElement) { + const url = elem.getAttribute("resource-name") if (!url) return await resourceServer.get(url).then( resp => { @@ -88,11 +96,11 @@ async function checkHref(elem: HTMLLinkElement) { } function checkPerms(className: string) { + // Scan elements with className and check the respose var rootElems = document.getElementsByClassName(className) Array.from(rootElems).forEach(elem => - Array.from(elem.children).forEach(elem => checkHref(elem)) + Array.from(elem.children).forEach(elem => checkResource(elem)) ) } - const app = createApp(App) From d44bb6218765d6ed5cd10f8534cf8568a8cdc3f2 Mon Sep 17 00:00:00 2001 From: phil Date: Thu, 13 Feb 2025 15:12:17 +0100 Subject: [PATCH 10/19] Fix some typings --- src/App.vue | 41 +++++++++++++++++++++++++---------------- src/ResourceButton.vue | 10 +++++----- src/main.ts | 10 +--------- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/App.vue b/src/App.vue index 08c0ee9..2b4aba5 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,11 +1,20 @@ + + diff --git a/src/TokenView.vue b/src/TokenView.vue new file mode 100644 index 0000000..91b34eb --- /dev/null +++ b/src/TokenView.vue @@ -0,0 +1,30 @@ + + + diff --git a/src/UserInfo.vue b/src/UserInfo.vue new file mode 100644 index 0000000..cfc1c31 --- /dev/null +++ b/src/UserInfo.vue @@ -0,0 +1,45 @@ + + + diff --git a/src/main.ts b/src/main.ts index b9bfc24..e2ab97d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,8 +1,8 @@ -import { createApp, ref } from 'vue' +import { createApp } from 'vue' import Keycloak from "keycloak-js" import VueKeycloakJs from '@dsb-norge/vue-keycloak-js' import axios, { type AxiosInstance } from 'axios' -import App from './App.vue' +import App from '@/App.vue' interface Settings { keycloakUri: string @@ -17,6 +17,9 @@ interface Settings { export interface Resource { name: string + default_resource_id: string + role_required: string + scope_required: string } export interface Resources { @@ -51,14 +54,12 @@ axios.get("settings.json").then().then( }, onReady(keycloak: Keycloak) { initializeTokenInterceptor(keycloak) - checkPerms('links-to-check') + app.mount("#app") }, }) - app.mount("#app") } ) - function initializeTokenInterceptor(keycloak: Keycloak) { authServer.interceptors.request.use(axiosSettings => { if (keycloak.authenticated) { @@ -80,27 +81,4 @@ function initializeTokenInterceptor(keycloak: Keycloak) { }) } -export async function checkResource(elem: HTMLLinkElement) { - const url = elem.getAttribute("resource-name") - if (!url) return - await resourceServer.get(url).then( - resp => { - elem.classList.add("hasResponseStatus") - elem.classList.add("status-" + resp.status) - elem.title = "Response code: " + resp.status + " - " + resp.statusText - }).catch(err => { - elem.classList.add("hasResponseStatus") - elem.classList.add("status-" + err.response.status) - elem.title = "Response code: " + err.response.status + " - " + err.response.statusText - }) -} - -function checkPerms(className: string) { - // Scan elements with className and check the respose - var rootElems = document.getElementsByClassName(className) - Array.from(rootElems).forEach(elem => - Array.from(elem.children).forEach(elem => checkResource(elem)) - ) -} - const app = createApp(App) From 7a379934399d53797d83cb361aff6ab40d497c2a Mon Sep 17 00:00:00 2001 From: phil Date: Fri, 21 Feb 2025 01:20:35 +0100 Subject: [PATCH 12/19] Fix typo --- src/TokenView.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/TokenView.vue b/src/TokenView.vue index 91b34eb..b8287bf 100644 --- a/src/TokenView.vue +++ b/src/TokenView.vue @@ -9,21 +9,21 @@ const keycloak = useKeycloak()

id token

-
+

access token

-
+

refresh token

-
+
From d2dcfb6e2e52eef3b90ab75407aaf540ae86a39e Mon Sep 17 00:00:00 2001 From: phil Date: Fri, 21 Feb 2025 13:45:18 +0100 Subject: [PATCH 13/19] Support third party resource providers --- public/styles.css | 3 +++ src/App.vue | 27 +++++++++++++++---- src/ResourceButton.vue | 10 ++++--- src/main.ts | 60 +++++++++++++++++++++++++++++++++--------- 4 files changed, 80 insertions(+), 20 deletions(-) diff --git a/public/styles.css b/public/styles.css index 36de6da..8d4804f 100644 --- a/public/styles.css +++ b/public/styles.css @@ -178,6 +178,9 @@ hr { border: none; cursor: pointer; } +.content .links-to-check span { + margin: auto; +} .token { overflow-wrap: anywhere; diff --git a/src/App.vue b/src/App.vue index c120088..006f88b 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,7 +1,9 @@