How to connect keycloak and Nuxt

RMAG news

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

The Loop VueJs Podcast

Please follow and like us:
Pin Share