import NextAuth, { type NextAuthConfig } from "next-auth" import Auth0Provider from "next-auth/providers/auth0" import { createLogger } from "@scandic-hotels/common/logger/createLogger" import { env } from "@/env/server" const authLogger = createLogger("auth") /* TODO: Get info for SAS token timeout and accordingly adjust pre-refresh time move to common/contants Do we need to handle refresh tokens at all, isn't that handled by the Auth0 provider? Needs to be verified */ const sasProvider = Auth0Provider({ id: "sas", name: "SAS", clientId: env.SAS_AUTH_CLIENTID, issuer: env.SAS_AUTH_ENDPOINT, checks: ["state"], authorization: { params: { audience: "eb-partner-api", }, }, client: { token_endpoint_auth_method: "none", }, }) const config: NextAuthConfig = { basePath: "/api/web/auth", debug: env.NEXTAUTH_DEBUG, trustHost: true, providers: [sasProvider], session: { strategy: "jwt", }, cookies: { sessionToken: { name: "sas-session", }, }, callbacks: { async signIn() { return true }, async jwt(params) { if (params.trigger === "signIn") { const accessToken = params.account?.access_token const expiresAt = params.account?.expires_at if (!accessToken) { throw new Error("AuthError: Missing access token") } if (!expiresAt) { throw new Error("AuthError: Missing expiry time") } return { ...params.token, loginType: "sas", access_token: accessToken, expires_at: expiresAt, } } return params.token }, async session({ session, token }) { return { ...session, error: token.error, user: session.user ? { ...session.user, id: token.sub, } : undefined, token: { access_token: token.access_token, expires_at: token.expires_at, error: token.error, }, } }, async redirect({ baseUrl, url }) { authLogger.debug(`[auth] deciding redirect URL`, { baseUrl, url }) if (url.startsWith("/")) { authLogger.debug( `[auth] relative URL accepted, returning: ${baseUrl}${url}` ) // Allows relative callback URLs return `${baseUrl}${url}` } else { // Assume absolute URL try { const parsedUrl = new URL(url) if (/\.scandichotels\.com$/.test(parsedUrl.hostname)) { authLogger.debug(`[auth] subdomain URL accepted, returning: ${url}`) // Allows any subdomains on all top level domains above return url } else if (parsedUrl.origin === baseUrl) { // Allows callback URLs on the same origin authLogger.debug(`[auth] origin URL accepted, returning: ${url}`) return url } } catch (e) { authLogger.error( `[auth] error parsing incoming URL for redirection`, e ) } } authLogger.debug(`[auth] URL denied, returning base URL: ${baseUrl}`) return baseUrl }, }, } export const { handlers: { GET, POST }, signIn, signOut, } = NextAuth(config) export const { auth } = NextAuth(config)