Move settings as dynamic json file; nice token info display
This commit is contained in:
parent
14c9091e77
commit
d17ba9f735
5 changed files with 106 additions and 42 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
node_modules/*
|
node_modules/*
|
||||||
dist/*
|
dist/*
|
||||||
|
settings.json
|
||||||
|
|
15
example_settings.json
Normal file
15
example_settings.json
Normal 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
|
||||||
|
}
|
|
@ -171,10 +171,6 @@ hr {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.from-keycloak-vue {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -202,6 +198,17 @@ hr {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resource .key {
|
.from-keycloak-vue {
|
||||||
|
margin: 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.token .key, .token .value {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.token .value {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
39
src/App.vue
39
src/App.vue
|
@ -1,14 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { authServer, resourceServer } from '@/main'
|
import { authServer, resourceServer, settings } from '@/main'
|
||||||
import type { AxiosResponseHeaders } from 'axios'
|
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import Keycloak from "keycloak-js"
|
|
||||||
import { useKeycloak } from '@dsb-norge/vue-keycloak-js'
|
import { useKeycloak } from '@dsb-norge/vue-keycloak-js'
|
||||||
import { settings } from '../settings'
|
|
||||||
|
|
||||||
let resource = ref({})
|
let resource = ref({})
|
||||||
const keycloak = useKeycloak()
|
const keycloak = useKeycloak()
|
||||||
const requestHeaders = ref<AxiosResponseHeaders | Partial<unknown> | undefined>()
|
|
||||||
|
|
||||||
function manuallyRefreshAccessToken() {
|
function manuallyRefreshAccessToken() {
|
||||||
// We set a high minValidity to force a token refresh
|
// 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
|
// Doesn't really go anywhere, but as you see from the headers in the request
|
||||||
// it contains the latest access token at all times
|
// it contains the latest access token at all times
|
||||||
const response = await authServer.get('/oidc-test-web')
|
const response = await authServer.get('/oidc-test-web')
|
||||||
requestHeaders.value = response.config.headers
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
|
@ -62,7 +57,10 @@ async function get_resource(id: string) {
|
||||||
<button @click="logout" class="logout">Logout</button>
|
<button @click="logout" class="logout">Logout</button>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<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">
|
<div class="actions">
|
||||||
<button @click="get_resource('time')">Time</button>
|
<button @click="get_resource('time')">Time</button>
|
||||||
<button @click="get_resource('bs')">BS</button>
|
<button @click="get_resource('bs')">BS</button>
|
||||||
|
@ -75,10 +73,31 @@ async function get_resource(id: string) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="from-keycloak-vue">
|
<div v-if="settings.tokenSandbox" class="from-keycloak-vue">
|
||||||
<button @click="doAuthenticatedRequest">Trigger request</button>
|
<hr>
|
||||||
<button @click="manuallyRefreshAccessToken">Refresh access token</button>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
76
src/main.ts
76
src/main.ts
|
@ -1,25 +1,62 @@
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import Keycloak from "keycloak-js"
|
import Keycloak from "keycloak-js"
|
||||||
import VueKeycloakJs from '@dsb-norge/vue-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 App from './App.vue'
|
||||||
import { settings } from "../settings"
|
|
||||||
|
|
||||||
export const authServer = axios.create({
|
interface Settings {
|
||||||
baseURL: '/',
|
keycloakUri: string
|
||||||
timeout: 10000
|
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) {
|
function initializeTokenInterceptor(keycloak: Keycloak) {
|
||||||
authServer.interceptors.request.use(axiosSettings => {
|
authServer.interceptors.request.use(axiosSettings => {
|
||||||
if (keycloak.authenticated) {
|
if (keycloak.authenticated) {
|
||||||
axiosSettings.headers.Authorization = `Bearer ${keycloak.token}`
|
axiosSettings.headers.Authorization = `Bearer ${keycloak.token}`
|
||||||
axiosSettings.headers.auth_provider = settings.auth_provider
|
axiosSettings.headers.auth_provider = settings.authProvider
|
||||||
}
|
}
|
||||||
return axiosSettings
|
return axiosSettings
|
||||||
}, error => {
|
}, error => {
|
||||||
|
@ -28,7 +65,7 @@ function initializeTokenInterceptor(keycloak: Keycloak) {
|
||||||
resourceServer.interceptors.request.use(axiosSettings => {
|
resourceServer.interceptors.request.use(axiosSettings => {
|
||||||
if (keycloak.authenticated) {
|
if (keycloak.authenticated) {
|
||||||
axiosSettings.headers.Authorization = `Bearer ${keycloak.token}`
|
axiosSettings.headers.Authorization = `Bearer ${keycloak.token}`
|
||||||
axiosSettings.headers.auth_provider = settings.auth_provider
|
axiosSettings.headers.auth_provider = settings.authProvider
|
||||||
}
|
}
|
||||||
return axiosSettings
|
return axiosSettings
|
||||||
}, error => {
|
}, error => {
|
||||||
|
@ -37,18 +74,3 @@ function initializeTokenInterceptor(keycloak: Keycloak) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const app = createApp(App)
|
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)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue