These are now defined in Netlify UI for dedicated environments (test, stage, production): AUTH_URL NEXTAUTH_URL PUBLIC_URL Code now falls back to incoming request host. Mainly used for deployment previews which do not have Akamai in front, meaning we do not need the above workaround as incoming request host matches the actual public facing host. When Akamai is in front, we lose the public facing host in Netlify's routing layer as they internally use `x-forwarded-for` and we can't claim it for our usage.
116 lines
3.4 KiB
TypeScript
116 lines
3.4 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server"
|
|
import { AuthError } from "next-auth"
|
|
|
|
import { Lang } from "@/constants/languages"
|
|
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: { 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"
|
|
|
|
console.log(
|
|
`[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 {
|
|
console.log(
|
|
`[login] missing returnUrl, using fallback: ${redirectToFallback}`
|
|
)
|
|
redirectTo = redirectToFallback
|
|
}
|
|
} else {
|
|
redirectTo = redirectToSearchParamValue || redirectToFallback
|
|
|
|
// Make relative URL to absolute URL
|
|
if (redirectTo.startsWith("/")) {
|
|
console.log(`[logout] make redirectTo absolute, from ${redirectTo}`)
|
|
redirectTo = new URL(redirectTo, publicURL).href
|
|
console.log(`[logout] make redirectTo absolute, to ${redirectTo}`)
|
|
}
|
|
|
|
try {
|
|
// Initiate the seamless logout flow
|
|
let redirectUrlValue
|
|
switch (context.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)
|
|
console.log(
|
|
`[logout] creating redirect to seamless logout: ${redirectUrl}`
|
|
)
|
|
redirectTo = redirectUrl.toString()
|
|
} catch (e) {
|
|
console.error(
|
|
"Unable to create URL for seamless logout, proceeding without it."
|
|
)
|
|
console.error(e)
|
|
}
|
|
}
|
|
|
|
try {
|
|
redirectTo = `${env.CURITY_ISSUER_USER}/authn/authenticate/logout?redirect_uri=${encodeURIComponent(redirectTo)}`
|
|
console.log(`[logout] final redirectUrl: ${redirectTo}`)
|
|
console.log({ logout_env: process.env })
|
|
|
|
/**
|
|
* 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) {
|
|
console.log(`[logout] redirecting to: ${redirectUrlObj.redirect}`)
|
|
return NextResponse.redirect(redirectUrlObj.redirect)
|
|
} else {
|
|
console.error(`[logout] missing redirectUrlObj reponse from signOut()`)
|
|
}
|
|
} catch (error) {
|
|
if (error instanceof AuthError) {
|
|
console.log({ signOutAuthError: error })
|
|
} else {
|
|
console.log({ signOutError: error })
|
|
}
|
|
}
|
|
|
|
return internalServerError()
|
|
}
|