Has anyone gotten Nuxt 3 to work with Keycloak?
I'm having a lot of trouble getting it to work, I was hoping to use Nuxt Auth but that's not done yet and I don't know when it might be out, but we're already talking about Nuxt 4? Am I missing something here?
2 Replies
Just saw this message, yes I'm using keycloak right now, except it only works on the client so only static sites.
then in your app you can call
// plugins/keycloak.client.ts
import Keycloak from 'keycloak-js'
export default defineNuxtPlugin(async () => {
const config = useRuntimeConfig()
// define new keycloak
const keycloak = new Keycloak({
url: config.public.keycloakAuthUrl,
realm: config.public.keycloakRealm,
clientId: config.public.keycloakClientId
})
try {
// init keycloak instance
await keycloak.init({
onLoad: 'check-sso',
responseMode: 'query',
pkceMethod: 'S256'
})
} catch (error) {
console.error('Failed to initialize Keycloak adapter: ', error)
}
return {
provide: {
// provide global keycloak instance
keycloak
}
}
})
// plugins/keycloak.client.ts
import Keycloak from 'keycloak-js'
export default defineNuxtPlugin(async () => {
const config = useRuntimeConfig()
// define new keycloak
const keycloak = new Keycloak({
url: config.public.keycloakAuthUrl,
realm: config.public.keycloakRealm,
clientId: config.public.keycloakClientId
})
try {
// init keycloak instance
await keycloak.init({
onLoad: 'check-sso',
responseMode: 'query',
pkceMethod: 'S256'
})
} catch (error) {
console.error('Failed to initialize Keycloak adapter: ', error)
}
return {
provide: {
// provide global keycloak instance
keycloak
}
}
})
const {$keycloak} = useNuxtApp()
I'm using sidebase-auth with keycloak:
import { NuxtAuthHandler } from "#auth";
import KeycloakProvider, {
type KeycloakProfile,
} from "next-auth/providers/keycloak";
const rtc = useRuntimeConfig();
export default NuxtAuthHandler({
secret: "somethingyoushoulddefinitelychangehere",
pages: {
signIn: "/login",
},
providers: [
// @ts-expect-error You need to use .default here for it to work during SSR. May be fixed via Vite at some point
KeycloakProvider.default({
clientId: rtc.keycloakClientId,
clientSecret: rtc.keycloakClientSecret,
issuer: rtc.keycloakIssuer,
profile(profile: KeycloakProfile) {
return {
uid: profile.sub,
name: profile.name ?? profile.preferred_username,
email: profile.email,
roles: profile.roles,
};
},
})
],
callbacks: {
// Callback when the JWT is created / updated, see https://next-auth.js.org/configuration/callbacks#jwt-callback
jwt: async ({ token, user }) => {
const isSignIn = user ? true : false;
if (isSignIn) {
token.uid = user ? user.uid || "" : "";
token.roles = user ? user.roles || [] : [];
}
return Promise.resolve(token);
},
// Callback whenever session is checked, see https://next-auth.js.org/configuration/callbacks#session-callback
session: async ({ session, token }) => {
session.roles = token.roles;
session.uid = token.uid;
return Promise.resolve(session);
},
},
});
import { NuxtAuthHandler } from "#auth";
import KeycloakProvider, {
type KeycloakProfile,
} from "next-auth/providers/keycloak";
const rtc = useRuntimeConfig();
export default NuxtAuthHandler({
secret: "somethingyoushoulddefinitelychangehere",
pages: {
signIn: "/login",
},
providers: [
// @ts-expect-error You need to use .default here for it to work during SSR. May be fixed via Vite at some point
KeycloakProvider.default({
clientId: rtc.keycloakClientId,
clientSecret: rtc.keycloakClientSecret,
issuer: rtc.keycloakIssuer,
profile(profile: KeycloakProfile) {
return {
uid: profile.sub,
name: profile.name ?? profile.preferred_username,
email: profile.email,
roles: profile.roles,
};
},
})
],
callbacks: {
// Callback when the JWT is created / updated, see https://next-auth.js.org/configuration/callbacks#jwt-callback
jwt: async ({ token, user }) => {
const isSignIn = user ? true : false;
if (isSignIn) {
token.uid = user ? user.uid || "" : "";
token.roles = user ? user.roles || [] : [];
}
return Promise.resolve(token);
},
// Callback whenever session is checked, see https://next-auth.js.org/configuration/callbacks#session-callback
session: async ({ session, token }) => {
session.roles = token.roles;
session.uid = token.uid;
return Promise.resolve(session);
},
},
});