While working in an internal project, I got the task of getting the connection between keycloak and our nuxt application.
After an hour of research, I found two feasible options to get this working fast and easy.
→ Using the keycloak-js
- manage the keycloak manually
<script setup>
import Keycloak from 'keycloak-js'
import { useKeycloak } from '@/stores/keycloak'
useHead({
title: 'Home page'
})
const config = useRuntimeConfig()
const store = useKeycloak()
const state = reactive({
loggedIn: false
})
if (config.public.keycloakDisabled) {
state.loggedIn = true
} else {
const initOptions = {
url: config.public.keycloakUrl,
realm: config.public.keycloakRealm,
clientId: config.public.keycloakClientId,
onLoad: 'login-required'
}
const keycloak = new Keycloak(initOptions)
keycloak
.init({ onLoad: initOptions.onLoad })
.then((auth) => {
if (!auth) {
window.location.reload()
} else {
store.setup(keycloak)
state.loggedIn = true
}
})
}
</script>
<template>
<div>
<div v-if="state.loggedIn">
<Header />
<NuxtPage />
</div>
</div>
</template>
With this option you don’t have public pages
→ Using # Nuxt OpenID-Connect
Module
that is using node-openid-client
With this option, you can have public routes by just extending the nuxt-config
openidConnect: {
addPlugin: true,
op: {
issuer: "http://keycloak:8080/realms/dev-realm", // change to your OP addrress
clientId: "CLIENT_ID",
clientSecret: "SECRET_KEY",
callbackUrl: "", // optional
scope: ["email", "profile", "address"],
},
config: {
debug: true,
response_type: "code",
secret: "oidc._sessionid",
cookie: { loginName: "" },
cookiePrefix: "oidc._",
cookieEncrypt: true,
cookieEncryptKey: "SECRET_KEY",
cookieEncryptIV: "ab83667c72eec9e4",
cookieEncryptALGO: "aes-256-cbc",
cookieMaxAge: 24 * 60 * 60, // default one day
cookieFlags: {
access_token: {
httpOnly: true,
secure: false,
},
},
},
},
Then create a middleware/auth.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
if (import.meta.server) {
return;
}
const isAuthRequired = to.meta.auth || false;
const oidc = useOidc();
if (isAuthRequired && !oidc.isLoggedIn) {
oidc.login(to.fullPath);
}
});
for public pages, you can set the meta attribute:
<script lang="ts" setup>
/**
*
* Component Description:Desc
*
* @author Reflect-Media <ismael@leamsigc.com>
* @version 0.0.1
*
* @todo [ ] Test the component
* @todo [ ] Integration test.
* @todo [✔] Update the typescript.
*/
definePageMeta({
auth: false,
layout: "public-view",
});
</script>
<template>
<div class="grid place-items-center">
<RegistrationForm />
</div>
</template>
<style scoped></style>
for the pages that need authentication:
<script lang="ts" setup>
/**
*
* Component Description:Desc
*
* @author Reflect-Media <reflect.media GmbH>
* @version 0.0.1
*
* @todo [ ] Test the component
* @todo [ ] Integration test.
* @todo [✔] Update the typescript.
*/
definePageMeta({
auth: true,
});
</script>
<template>
<div>content</div>
</template>
<style scoped></style>
The other option is to create
-
layouts/default.vue
→ that set the auth to true by default -
layouts/publicView.vue
→ will set the auth to false.
Resources:
Module
Example with keycloak-js
**Happy hacking!
Working on the audio version