import { type NextRequest, NextResponse } from "next/server" import { AuthError } from "next-auth" import { Lang } from "@scandic-hotels/common/constants/language" import { logger } from "@scandic-hotels/common/logger" import { env } from "@/env/server" import { internalServerError } from "@/server/errors/next" import { getPublicURL } from "@/server/utils" import { signOut } from "@/auth" export async function GET( request: NextRequest, context: { params: Promise<{ lang: Lang }> } ) { const publicURL = getPublicURL(request) let redirectTo: string = "" const returnUrl = request.headers.get("x-returnurl") const isSeamless = request.headers.get("x-logout-source") === "seamless" logger.debug( `[logout] source: ${request.headers.get("x-logout-source") || "normal"}` ) const redirectToSearchParamValue = request.nextUrl.searchParams.get("redirectTo") const redirectToFallback = "/" if (isSeamless) { if (returnUrl) { redirectTo = returnUrl } else { logger.debug( `[login] missing returnUrl, using fallback: ${redirectToFallback}` ) redirectTo = redirectToFallback } } else { redirectTo = redirectToSearchParamValue || redirectToFallback // Make relative URL to absolute URL if (redirectTo.startsWith("/")) { logger.debug(`[logout] make redirectTo absolute, from ${redirectTo}`) redirectTo = new URL(redirectTo, publicURL).href logger.debug(`[logout] make redirectTo absolute, to ${redirectTo}`) } try { // Initiate the seamless logout flow let redirectUrlValue const params = await context.params switch (params.lang) { case Lang.da: redirectUrlValue = env.SEAMLESS_LOGOUT_DA break case Lang.de: redirectUrlValue = env.SEAMLESS_LOGOUT_DE break case Lang.en: redirectUrlValue = env.SEAMLESS_LOGOUT_EN break case Lang.fi: redirectUrlValue = env.SEAMLESS_LOGOUT_FI break case Lang.no: redirectUrlValue = env.SEAMLESS_LOGOUT_NO break case Lang.sv: redirectUrlValue = env.SEAMLESS_LOGOUT_SV break } const redirectUrl = new URL(redirectUrlValue) logger.debug( `[logout] creating redirect to seamless logout: ${redirectUrl}` ) redirectTo = redirectUrl.toString() } catch (e) { logger.error( "Unable to create URL for seamless logout, proceeding without it.", e ) } } try { redirectTo = `${env.CURITY_ISSUER_USER}/authn/authenticate/logout?redirect_uri=${encodeURIComponent(redirectTo)}` logger.debug(`[logout] final redirectUrl: ${redirectTo}`) /** * Passing `redirect: false` to `signOut` will return a result object * instead of automatically redirecting inside of `signOut`. * https://github.com/nextauthjs/next-auth/blob/3c035ec/packages/next-auth/src/lib/actions.ts#L104 */ const redirectUrlObj = await signOut({ redirectTo, redirect: false, }) if (redirectUrlObj) { logger.debug(`[logout] redirecting to: ${redirectUrlObj.redirect}`) return NextResponse.redirect(redirectUrlObj.redirect) } else { logger.error(`[logout] missing redirectUrlObj reponse from signOut()`) } } catch (error) { if (error instanceof AuthError) { logger.error("signOutAuthError", { signOutAuthError: error }) } else { logger.error("signOutError", { signOutError: error }) } } return internalServerError() }