Move settings as dynamic json file; nice token info display

This commit is contained in:
phil 2025-01-31 03:12:36 +01:00
parent 14c9091e77
commit d17ba9f735
5 changed files with 106 additions and 42 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
node_modules/*
dist/*
settings.json

15
example_settings.json Normal file
View file

@ -0,0 +1,15 @@
{
"keycloakUri": "https://philo.ydns.eu/auth",
"realm": "test",
"authProvider": "keycloak",
"sso": false,
"clientId": "oidc-test-web",
"resourceServerUrl": "https://philo.ydns.eu/oidc-test/resource",
"resourceScopes": [
"get:time",
"get:bs"
],
"sslCertFile": "/path/to/cert.pem",
"sslKeyFile": "/path/to/key.pem",
"tokenSandbox": true
}

View file

@ -171,10 +171,6 @@ hr {
font-family: monospace;
}
.from-keycloak-vue {
display: none;
}
.actions {
display: flex;
justify-content: center;
@ -202,6 +198,17 @@ hr {
text-align: center;
}
.resource .key {
.from-keycloak-vue {
margin: 0 1em;
}
.key {
font-weight: bold;
}
.token .key, .token .value {
display: inline;
}
.token .value {
padding-left: 1em;
}

View file

@ -1,14 +1,10 @@
<script setup lang="ts">
import { authServer, resourceServer } from '@/main'
import type { AxiosResponseHeaders } from 'axios'
import { authServer, resourceServer, settings } from '@/main'
import { ref } from 'vue'
import Keycloak from "keycloak-js"
import { useKeycloak } from '@dsb-norge/vue-keycloak-js'
import { settings } from '../settings'
let resource = ref({})
const keycloak = useKeycloak()
const requestHeaders = ref<AxiosResponseHeaders | Partial<unknown> | undefined>()
function manuallyRefreshAccessToken() {
// We set a high minValidity to force a token refresh
@ -19,7 +15,6 @@ async function doAuthenticatedRequest() {
// Doesn't really go anywhere, but as you see from the headers in the request
// it contains the latest access token at all times
const response = await authServer.get('/oidc-test-web')
requestHeaders.value = response.config.headers
}
function logout() {
@ -62,7 +57,10 @@ async function get_resource(id: string) {
<button @click="logout" class="logout">Logout</button>
</div>
<hr>
<p class="center">Fetch resources from a resource server (at {{ settings.url }}) with the authentication token:</p>
<p class="center">
Fetch resources from a resource server (at {{ settings.resourceServerUrl }})
with your authentication token:
</p>
<div class="actions">
<button @click="get_resource('time')">Time</button>
<button @click="get_resource('bs')">BS</button>
@ -75,10 +73,31 @@ async function get_resource(id: string) {
</div>
</div>
</div>
<div class="from-keycloak-vue">
<button @click="doAuthenticatedRequest">Trigger request</button>
<div v-if="settings.tokenSandbox" class="from-keycloak-vue">
<hr>
<button @click="manuallyRefreshAccessToken">Refresh access token</button>
<div class="token" :innerText="requestHeaders?.toString()">
<div>
<h2>idToken</h2>
<div class="token">
<div v-for="(value, key) in keycloak.idTokenParsed">
<div class=" key">{{ key }}</div>
<div class="value">{{ value }}</div>
</div>
</div>
<h2>access token</h2>
<div class="token">
<div v-for="(value, key) in keycloak.tokenParsed">
<div class=" key">{{ key }}</div>
<div class="value">{{ value }}</div>
</div>
</div>
<h2>refresh token</h2>
<div class="token">
<div v-for="(value, key) in keycloak.refreshTokenParsed">
<div class=" key">{{ key }}</div>
<div class="value">{{ value }}</div>
</div>
</div>
</div>
</div>
</div>

View file

@ -1,25 +1,62 @@
import { createApp } from 'vue'
import Keycloak from "keycloak-js"
import VueKeycloakJs from '@dsb-norge/vue-keycloak-js'
import axios from 'axios'
import axios, { type AxiosInstance } from 'axios'
import App from './App.vue'
import { settings } from "../settings"
export const authServer = axios.create({
baseURL: '/',
timeout: 10000
})
interface Settings {
keycloakUri: string
realm: string
clientId: string
sso: boolean
resourceServerUrl: string
resourceScopes: string[]
authProvider: string
sslCertFile: string
sslKeyFile: string
tokenSandbox: boolean
}
export let settings: Settings
export let authServer: AxiosInstance
export let resourceServer: AxiosInstance
axios.get("settings.json").then().then(
resp => {
settings = resp.data
resourceServer = axios.create({
baseURL: settings.resourceServerUrl,
timeout: 10000
})
authServer = axios.create({
baseURL: '/',
timeout: 10000
})
app.use(VueKeycloakJs, {
config: {
url: settings.keycloakUri,
realm: settings.realm,
clientId: settings.clientId
},
init: {
onLoad: settings.sso ? "check-sso" : "login-required",
scope: "openid email profile " + settings.resourceScopes.join(" ")
},
onReady(keycloak: Keycloak) {
initializeTokenInterceptor(keycloak)
},
})
app.mount("#app")
}
)
export const resourceServer = axios.create({
baseURL: settings.url,
timeout: 10000
})
function initializeTokenInterceptor(keycloak: Keycloak) {
authServer.interceptors.request.use(axiosSettings => {
if (keycloak.authenticated) {
axiosSettings.headers.Authorization = `Bearer ${keycloak.token}`
axiosSettings.headers.auth_provider = settings.auth_provider
axiosSettings.headers.auth_provider = settings.authProvider
}
return axiosSettings
}, error => {
@ -28,7 +65,7 @@ function initializeTokenInterceptor(keycloak: Keycloak) {
resourceServer.interceptors.request.use(axiosSettings => {
if (keycloak.authenticated) {
axiosSettings.headers.Authorization = `Bearer ${keycloak.token}`
axiosSettings.headers.auth_provider = settings.auth_provider
axiosSettings.headers.auth_provider = settings.authProvider
}
return axiosSettings
}, error => {
@ -37,18 +74,3 @@ function initializeTokenInterceptor(keycloak: Keycloak) {
}
const app = createApp(App)
app.mount('#app')
app.use(VueKeycloakJs, {
config: {
url: 'https://philo.ydns.eu/auth/',
realm: 'test',
clientId: 'oidc-test-web',
},
init: {
onLoad: settings.sso ? 'check-sso' : 'login-required',
scope: "openid email profile get:time get:bs"
},
onReady(keycloak: Keycloak) {
initializeTokenInterceptor(keycloak)
},
})