diff --git a/apps/partner-sas/app/[lang]/(auth)/login/route.ts b/apps/partner-sas/app/[lang]/(auth)/login/route.ts new file mode 100644 index 000000000..c90b1a92a --- /dev/null +++ b/apps/partner-sas/app/[lang]/(auth)/login/route.ts @@ -0,0 +1,100 @@ +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" + +import type { Lang } from "@scandic-hotels/common/constants/language" + +export async function GET( + request: NextRequest, + context: { params: Promise<{ lang: Lang }> } +) { + const contextParams = await context.params + const publicURL = getPublicURL(request) + + let redirectHeaders: Headers | undefined = undefined + let redirectTo: string + + 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}` + ) + + 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" + ) + + const SAS_LANGUAGE_MAP: Record = { + no: "nb", + sv: "sv", + fi: "fi", + da: "da", + en: "en", + de: "de", + } + + try { + logger.debug(`[login] final redirectUrl: ${redirectTo}`) + + /** Record is next-auth typings */ + const params = { + ui_locales: SAS_LANGUAGE_MAP[contextParams.lang], + scope: ["openid", "profile", "email"].join(" "), + } satisfies Record + + /** + * 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( + "sas", + { + 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() +} diff --git a/apps/partner-sas/app/[lang]/(auth)/logout/route.ts b/apps/partner-sas/app/[lang]/(auth)/logout/route.ts new file mode 100644 index 000000000..a4984c591 --- /dev/null +++ b/apps/partner-sas/app/[lang]/(auth)/logout/route.ts @@ -0,0 +1,17 @@ +import { type NextRequest } from "next/server" + +import { getPublicURL } from "@/server/utils" + +import { signOut } from "@/auth" + +import type { Lang } from "@scandic-hotels/common/constants/language" + +export async function GET( + request: NextRequest, + _context: { params: Promise<{ lang: Lang }> } +) { + const publicURL = getPublicURL(request) + + const redirectTo: string = publicURL + await signOut({ redirectTo, redirect: true }) +} diff --git a/apps/partner-sas/app/[lang]/layout.tsx b/apps/partner-sas/app/[lang]/layout.tsx index 47578223b..4f76be8e5 100644 --- a/apps/partner-sas/app/[lang]/layout.tsx +++ b/apps/partner-sas/app/[lang]/layout.tsx @@ -6,10 +6,9 @@ import "../../globals.css" import { ReactQueryDevtools } from "@tanstack/react-query-devtools" import Script from "next/script" +import { SessionProvider } from "next-auth/react" import { BookingFlowConfig } from "@scandic-hotels/booking-flow/BookingFlowConfig" -import { BookingFlowContextProvider } from "@scandic-hotels/booking-flow/BookingFlowContextProvider" -import { BookingFlowTrackingProvider } from "@scandic-hotels/booking-flow/BookingFlowTrackingProvider" import { NuqsAdapter } from "@scandic-hotels/booking-flow/utils/nuqs" import { Lang } from "@scandic-hotels/common/constants/language" import { ToastHandler } from "@scandic-hotels/design-system/ToastHandler" @@ -25,20 +24,9 @@ import { getMessages } from "@/i18n" import ClientIntlProvider from "@/i18n/Provider" import { setLang } from "@/i18n/serverContext" +import { BookingFlowProviders } from "../../components/BookingFlowProviders" import { Footer } from "../../components/Footer/Footer" import { Header } from "../../components/Header/Header" -import { - trackAccordionItemOpen, - trackBedSelection, - trackBookingSearchClick, - trackBreakfastSelection, - trackGenericEvent, - trackGlaSaveCardAttempt, - trackLoginClick, - trackOpenSidePeek, - trackPaymentEvent, - trackUpdatePaymentMethod, -} from "../utils/tracking" import type { Metadata } from "next" @@ -82,35 +70,18 @@ export default async function RootLayout(props: RootLayoutProps) {
- - - - - - - + + + + {/* TODO handle onError */} + + + +
{props.bookingwidget} @@ -119,13 +90,13 @@ export default async function RootLayout(props: RootLayoutProps) { - - - - - - - + + + + + + +