import { NextAuthOptions, User as NextAuthUser, Account, Profile, JWT as NextAuthJWT } from 'next-auth'; import KeycloakProvider from 'next-auth/providers/keycloak'; interface User extends NextAuthUser { id: string; email: string; name: string; role: string[]; first_name: string; last_name: string; username: string; } interface Session { user: User; accessToken: string; } interface JWT extends Omit { sub: string; email: string | null; name: string | null; role: string[]; username: string; first_name: string; last_name: string; accessToken: string; refreshToken: string; accessTokenExpires: number; error?: string; } interface KeycloakProfile extends Profile { sub: string; email?: string; name?: string; roles?: string[]; preferred_username?: string; given_name?: string; family_name?: string; } export const authOptions: NextAuthOptions = { providers: [ KeycloakProvider({ clientId: process.env.KEYCLOAK_CLIENT_ID!, clientSecret: process.env.KEYCLOAK_CLIENT_SECRET!, issuer: process.env.KEYCLOAK_ISSUER!, authorization: { params: { scope: 'openid email profile', }, }, }), ], session: { strategy: 'jwt', maxAge: 30 * 24 * 60 * 60, // 30 days }, callbacks: { async jwt({ token, account, profile }) { if (account && profile) { const keycloakProfile = profile as KeycloakProfile; token.accessToken = account.access_token ?? ''; token.refreshToken = account.refresh_token ?? ''; token.accessTokenExpires = account.expires_at ?? 0; token.sub = keycloakProfile.sub; token.role = keycloakProfile.roles ?? []; token.username = keycloakProfile.preferred_username ?? ''; token.first_name = keycloakProfile.given_name ?? ''; token.last_name = keycloakProfile.family_name ?? ''; } return token; }, async session({ session, token }) { console.log('Session callback - token:', token); console.log('Session callback - session before:', session); if (token.error) { throw new Error(token.error); } // Only update session if token has changed if (session.user?.id !== token.sub) { session.user = { id: token.sub, email: token.email ?? '', name: token.name ?? '', role: token.role, first_name: token.first_name, last_name: token.last_name, username: token.username, }; } session.accessToken = token.accessToken; console.log('Session callback - session after:', session); return session; }, }, pages: { signIn: '/signin', error: '/signin', }, };