feat(LOY-403): removed seamless login/logout * feat(LOY-403): removed seamless login/logout Approved-by: Joakim Jäderberg
146 lines
4.7 KiB
TypeScript
146 lines
4.7 KiB
TypeScript
import { type NextRequest, NextResponse } from "next/server"
|
|
import { AuthError } from "next-auth"
|
|
|
|
import { logger } from "@scandic-hotels/common/logger"
|
|
|
|
import { internalServerError } from "@/server/errors/next"
|
|
import { getPublicURL } from "@/server/utils"
|
|
|
|
import { signIn } from "@/auth"
|
|
|
|
export async function GET(
|
|
request: NextRequest,
|
|
context: RouteContext<"/[lang]/login">
|
|
) {
|
|
const contextParams = await context.params
|
|
const publicURL = getPublicURL(request)
|
|
|
|
let redirectHeaders: Headers | undefined = undefined
|
|
let redirectTo: string
|
|
|
|
const returnUrl = request.headers.get("x-returnurl")
|
|
const isMFA = request.headers.get("x-login-source") === "mfa"
|
|
const isSeamlessMagicLink =
|
|
request.headers.get("x-login-source") === "seamless-magiclink"
|
|
|
|
logger.debug(
|
|
`[login] source: ${request.headers.get("x-login-source") || "normal"}`
|
|
)
|
|
|
|
const redirectToCookieValue = request.cookies.get("redirectTo")?.value // Cookie gets set by authRequired middleware
|
|
const redirectToSearchParamValue =
|
|
request.nextUrl.searchParams.get("redirectTo")
|
|
const redirectToFallback = "/"
|
|
|
|
logger.debug(`[login] redirectTo cookie value: ${redirectToCookieValue}`)
|
|
logger.debug(
|
|
`[login] redirectTo search param value: ${redirectToSearchParamValue}`
|
|
)
|
|
|
|
if (isSeamlessMagicLink || isMFA) {
|
|
if (returnUrl) {
|
|
redirectTo = returnUrl
|
|
} else {
|
|
logger.debug(
|
|
`[login] missing returnUrl, using fallback: ${redirectToFallback}`
|
|
)
|
|
redirectTo = redirectToFallback
|
|
}
|
|
} else {
|
|
redirectTo =
|
|
redirectToCookieValue || redirectToSearchParamValue || redirectToFallback
|
|
|
|
// Make relative URL to absolute URL
|
|
if (redirectTo.startsWith("/")) {
|
|
logger.debug(`[login] make redirectTo absolute, from ${redirectTo}`)
|
|
redirectTo = new URL(redirectTo, publicURL).href
|
|
logger.debug(`[login] make redirectTo absolute, to ${redirectTo}`)
|
|
}
|
|
|
|
// Clean up cookie from authRequired middleware
|
|
redirectHeaders = new Headers()
|
|
redirectHeaders.append(
|
|
"set-cookie",
|
|
"redirectTo=; Expires=Thu, 01 Jan 1970 00:00:00 UTC; Path=/; HttpOnly; SameSite=Lax"
|
|
)
|
|
}
|
|
|
|
try {
|
|
logger.debug(`[login] final redirectUrl: ${redirectTo}`)
|
|
|
|
/** Record<string, any> is next-auth typings */
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const params: Record<string, any> = {
|
|
ui_locales: contextParams.lang,
|
|
scope: [
|
|
"openid",
|
|
"profile",
|
|
"booking",
|
|
"profile_link",
|
|
"profile_matchtier",
|
|
"profile_point_transfer",
|
|
"availability",
|
|
],
|
|
/**
|
|
* The `acr_values` param is used to make Curity display the proper login
|
|
* page for Scandic. Without the parameter Curity presents some choices
|
|
* to the user which we do not want.
|
|
*/
|
|
acr_values: "urn:com:scandichotels:scandic",
|
|
|
|
/**
|
|
* Both of the below two params are required to send for initiating login as well
|
|
* because user might choose to do Email link login.
|
|
* */
|
|
// The `for_origin` param is used to make Curity email login functionality working.
|
|
for_origin: publicURL,
|
|
// This is new param set for differentiate between the Magic link login of New web and current web
|
|
version: "2",
|
|
}
|
|
|
|
if (isMFA) {
|
|
// Append profile_update scope for MFA
|
|
params.scope.push("profile_update")
|
|
/**
|
|
* The below acr value is required as for New Web same Curity Client is used for MFA
|
|
* while in current web it is being setup using different Curity Client
|
|
*/
|
|
params.acr_values = "urn:com:scandichotels:scandic-otp"
|
|
} else if (isSeamlessMagicLink) {
|
|
params.acr_values = "urn:com:scandichotels:scandic-email"
|
|
}
|
|
params.scope = params.scope.join(" ")
|
|
/**
|
|
* Passing `redirect: false` to `signIn` will return the URL instead of
|
|
* automatically redirecting to it inside of `signIn`.
|
|
* https://github.com/nextauthjs/next-auth/blob/3c035ec/packages/next-auth/src/lib/actions.ts#L76
|
|
*/
|
|
const redirectUrl = await signIn(
|
|
"curity",
|
|
{
|
|
redirectTo,
|
|
redirect: false,
|
|
},
|
|
params
|
|
)
|
|
|
|
if (redirectUrl) {
|
|
const redirectOpts = {
|
|
headers: redirectHeaders,
|
|
}
|
|
logger.debug(`[login] redirecting to: ${redirectUrl}`, redirectOpts)
|
|
return NextResponse.redirect(redirectUrl, redirectOpts)
|
|
} else {
|
|
logger.error(`[login] missing redirectUrl reponse from signIn()`)
|
|
}
|
|
} catch (error) {
|
|
if (error instanceof AuthError) {
|
|
logger.error("signInAuthError", { signInAuthError: error })
|
|
} else {
|
|
logger.error("signInError", { signInError: error })
|
|
}
|
|
}
|
|
|
|
return internalServerError()
|
|
}
|