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
Top comments (1)
Is there a better way to do this? do you have any questions or want to see the example repo, just let me know