import NextAuth from "next-auth"; import Credentials from "next-auth/providers/credentials"; import Keycloak from "next-auth/providers/keycloak"; const SERVER_API_URL = process.env.SERVER_API_URL || "http://backend:8080"; const providers: any[] = [ Credentials({ name: "local", credentials: { username: { label: "Username", type: "text" }, password: { label: "Password", type: "password" }, }, async authorize(credentials) { if (!credentials?.username || !credentials?.password) return null; const res = await fetch(`${SERVER_API_URL}/api/auth/local-login`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username: credentials.username, password: credentials.password, }), }); if (!res.ok) return null; const user = await res.json(); return { id: String(user.id), name: user.username, email: user.email, role: user.role, }; }, }), ]; if (process.env.AUTH_KEYCLOAK_ISSUER) { providers.push( Keycloak({ clientId: process.env.AUTH_KEYCLOAK_ID!, clientSecret: process.env.AUTH_KEYCLOAK_SECRET!, issuer: process.env.AUTH_KEYCLOAK_ISSUER!, }) ); } export const { handlers: { GET, POST }, auth, signIn, signOut, } = NextAuth({ providers, callbacks: { async signIn({ user, account, profile }) { if (account?.provider === "keycloak" && profile) { const keycloakId = profile.sub as string; const email = (profile.email as string) || ""; const res = await fetch(`${SERVER_API_URL}/api/auth/lookup-binding`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ keycloakId, email }), }); if (!res.ok) return false; const data = await res.json(); if (data.bound) { (user as any).id = String(data.user.id); (user as any).role = data.user.role; return true; } return `/bind-account?keycloakId=${encodeURIComponent(keycloakId)}&email=${encodeURIComponent(email)}`; } return true; }, async jwt({ token, user }) { if (user) { token.id = user.id; token.role = (user as any).role; } return token; }, async session({ session, token }) { if (session.user) { (session.user as any).id = token.id; (session.user as any).role = token.role; } return session; }, }, pages: { signIn: "/login", error: "/login", }, session: { strategy: "jwt", }, });