I have a Nuxt3 app which I want to secure with Keycloak. For the integration, I use the keycloak-js library, which is defined as a plugin:
plugins/keycloak.client.ts
import Keycloak from 'keycloak-js';
import type {KeycloakConfig} from 'keycloak-js';
export default defineNuxtPlugin((nuxtApp) => {
const runtimeConfig = useRuntimeConfig();
const initOptions: KeycloakConfig = {
url: runtimeConfig.public.KEYCLOAK_URL!,
realm: runtimeConfig.public.KEYCLOAK_REALM!,
clientId: runtimeConfig.public.KEYCLOAK_CLIENT_ID!,
};
const keycloak = new Keycloak(initOptions);
nuxtApp.$keycloak = keycloak;
keycloak
.init({
onLoad: 'check-sso',
});
console.log('KeyCloak Plugin Loaded: ', nuxtApp.$keycloak);
});
The console logs this correctly.
For test purposes, I have a simple app.vue:
app.vue
<script setup lang="ts">
import Keycloak from 'keycloak-js';
const keycloak: Keycloak = useNuxtApp()['$keycloak'] as Keycloak
</script>
<template>
<div>
<div>
Authenticated?
{{keycloak.authenticated}}
</div>
<br/>
<button @click="keycloak.login()">Login via Keycloak</button>
<button @click="keycloak.logout()">Logout from Keycloak</button>
</div>
</template>
Logging in and out works and the log of the keycloak object shows the correct value. This page always displays false when I load it, even if authenticated shows up as true in the console. However, if I do a small change in the code and the app hot-reloads, the correct value is shown (until the next refresh).
What's more, if I do:
console.log(keycloak);
console.log(keycloak.authenticated);
The log of the complete object will show the value to be true, but the second log will show false.
I should add that Nuxt is quite new for me. With my half-knowledge, I tried:
SSR is disabled in the nuxt.config.ts.
I'm fresh out of ideas.
What am I missing?
keycloak.init
returns a Promise. keycloak.authenticated
is read before the keycloak instance is initiated. Furthermore, keycloak.authenticated
is not reactive, thus mutating its value will not reflect in the template.
<script setup lang="ts">
import Keycloak from 'keycloak-js';
const keycloak: Keycloak = useNuxtApp()['$keycloak'] as Keycloak
const authenticated = ref(false)
keycloak.onReady = (v: boolean) => { authenticated.value = v }
</script>
<template>
<div>
<div>
Authenticated?
{{authenticated}}
</div>
<br/>
<button @click="keycloak.login()">Login via Keycloak</button>
<button @click="keycloak.logout()">Logout from Keycloak</button>
</div>
</template>
await the initialization of keycloak
in nuxt plugin
export default defineNuxtPlugin({
name: 'keycloak',
order: 0,
async setup() {
await keycloak.init({ onLoad: 'check-sso' })
},
})