// server/api/auth/[...].ts import KeycloakProvider from "next-auth/providers/keycloak"; import CredentialsProvider from "next-auth/providers/credentials"; import { NuxtAuthHandler } from "#auth"; export default NuxtAuthHandler({ // TODO: SET A STRONG SECRET, SEE https://sidebase.io/nuxt-auth/configuration/nuxt-auth-handler#secret secret: process.env.AUTH_SECRET || "my-auth-secret", // TODO: ADD YOUR OWN AUTHENTICATION PROVIDER HERE, READ THE DOCS FOR MORE: https://sidebase.io/nuxt-auth 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: process.env.KEYCLOAK_CLIENT_ID, clientSecret: process.env.KEYCLOAK_CLIENT_SECRET, issuer: process.env.KEYCLOAK_ISSUER, // authorization: { // params: { // redirect_uri: // "http://meninjar.dev.rssa.id:3000/api/auth/callback/keycloak", // }, // }, profile(profile: any) { // Map Keycloak profile to user object return { id: profile.sub, name: profile.name, email: profile.email, image: profile.picture }; } }), // @ts-expect-error You need to use .default here for it to work during SSR. May be fixed via Vite at some point CredentialsProvider.default({ // The name to display on the sign in form (e.g. 'Sign in with...') name: "Credentials", // The credentials is used to generate a suitable form on the sign in page. // You can specify whatever fields you are expecting to be submitted. // e.g. domain, username, password, 2FA token, etc. // You can pass any HTML attribute to the tag through the object. credentials: { username: { label: "Username", type: "text", placeholder: "(hint: jsmith)" }, password: { label: "Password", type: "password", placeholder: "(hint: hunter2)" } }, authorize(credentials: any) { console.warn( "ATTENTION: You should replace this with your real providers or credential provider logic! The current setup is not safe" ); // You need to provide your own logic here that takes the credentials // submitted and returns either a object representing a user or value // that is false/null if the credentials are invalid. // NOTE: THE BELOW LOGIC IS NOT SAFE OR PROPER FOR AUTHENTICATION! const user = { id: "1", name: "J Smith", username: "jsmith", password: "hunter2" }; if ( credentials?.username === user.username && credentials?.password === user.password ) { // Any object returned will be saved in `user` property of the JWT return user; } else { console.error( "Warning: Malicious login attempt registered, bad credentials provided" ); // If you return null then an error will be displayed advising the user to check their details. return null; // You can also Reject this callback with an Error thus the user will be sent to the error page with the error message as a query parameter } } }) ], pages: { signIn: "/auth/login", signOut: "/auth/logout" // error: '/auth/error', // verifyRequest: '/auth/verify-request', // newUser: '/auth/new-user' }, callbacks: { async jwt({ token, user, account }: { token: any; user: any; account: any; }) { try { // Parse access token if it exists if (account && account.access_token) { token.access_token_payload = JSON.parse( atob(account.access_token.split(".")[1]) ); token.jwt = account.access_token; } } catch (error) { console.error("Error parsing access token:", error); } // Merge all relevant Keycloak response data into token if (account) { token.id_token = account.id_token; // Do not overwrite token.access_token after parsing // token.access_token = account.access_token; token.refresh_token = account.refresh_token; token.expires_at = account.expires_at; token.scope = account.scope; } if (user) { token.user = user; } return token; }, async session({ session, token }: { session: any; token: any }) { try { // Include all relevant token data into session session.id_token = token.id_token; session.access_token = token.access_token; session.access_token_payload = token.access_token_payload; session.refresh_token = token.refresh_token; session.expires_at = token.expires_at; session.scope = token.scope; session.user = token.user; session.jwt = token.jwt; return session; } catch (error) { console.error("Error in session callback:", error); return session; } }, async redirect({ url, baseUrl }: { url: string; baseUrl: string }) { // Redirect to home page after login return baseUrl; } } });