diff --git a/.env.local.example b/.env.local.example index 911804e9c..d4a0df527 100644 --- a/.env.local.example +++ b/.env.local.example @@ -16,4 +16,10 @@ NEXTAUTH_REDIRECT_PROXY_URL="http://localhost:3000/api/auth" NEXTAUTH_SECRET="" NEXTAUTH_URL="http://localhost:3000/api/auth" REVALIDATE_SECRET="" +SEAMLESS_LOGIN_DA="http://www.example.dk/updatelogin" +SEAMLESS_LOGIN_DE="http://www.example.de/updatelogin" +SEAMLESS_LOGIN_EN="http://www.example.com/updatelogin" +SEAMLESS_LOGIN_FI="http://www.example.fi/updatelogin" +SEAMLESS_LOGIN_NO="http://www.example.no/updatelogin" +SEAMLESS_LOGIN_SE="http://www.example.se/updatelogin" WEBVIEW_ENCRYPTION_KEY="MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=" diff --git a/app/[lang]/(live)/(public)/login/route.ts b/app/[lang]/(live)/(public)/login/route.ts index 8b6ed8105..dadcd452a 100644 --- a/app/[lang]/(live)/(public)/login/route.ts +++ b/app/[lang]/(live)/(public)/login/route.ts @@ -2,18 +2,59 @@ import { NextRequest, NextResponse } from "next/server" import { AuthError } from "next-auth" import { signIn } from "@/auth" -import { badRequest } from "@/server/errors/next" - -import type { Lang } from "@/constants/languages" +import { Lang } from "@/constants/languages" +import { env } from "@/env/server" +import { badRequest, internalServerError } from "@/server/errors/next" export async function GET( request: NextRequest, context: { params: { lang: Lang } } ) { - const redirectTo = + const returnUrl = request.headers.get("x-returnurl") + + // If all else fails, always redirect to startpage + const finalDestination = + returnUrl || request.headers.get("x-redirect-to") || request.nextUrl.searchParams.get("redirectTo") || - undefined + request.headers.get("Referer") || + "/" + + let redirectTo = finalDestination + if (!returnUrl) { + // This is a regular login request, not a seamless login request + // We should initiate the seamless login flow + try { + let redirectUrlValue + switch (context.params.lang) { + case Lang.da: + redirectUrlValue = env.SEAMLESS_LOGIN_DA + break + case Lang.de: + redirectUrlValue = env.SEAMLESS_LOGIN_DE + break + case Lang.en: + redirectUrlValue = env.SEAMLESS_LOGIN_EN + break + case Lang.fi: + redirectUrlValue = env.SEAMLESS_LOGIN_FI + break + case Lang.no: + redirectUrlValue = env.SEAMLESS_LOGIN_NO + break + case Lang.sv: + redirectUrlValue = env.SEAMLESS_LOGIN_SV + break + } + const redirectUrl = new URL(redirectUrlValue) + redirectUrl.searchParams.set("returnurl", finalDestination) + redirectTo = redirectUrl.toString() + } catch (e) { + console.error("Unable to create URL for seamless login") + console.error(e) + return internalServerError() + } + } try { /** diff --git a/auth.ts b/auth.ts index f61ca286c..530238896 100644 --- a/auth.ts +++ b/auth.ts @@ -85,8 +85,10 @@ export const config = { // Assume absolute URL try { const parsedUrl = new URL(url) - if (parsedUrl.hostname.endsWith(".scandichotels.com")) { - // Allows **.scandichotels.com + if ( + /\.scandichotels\.(dk|de|com|fi|no|se)$/.test(parsedUrl.hostname) + ) { + // Allows any subdomains on all top level domains above return url } else if (parsedUrl.origin === baseUrl) { // Allows callback URLs on the same origin diff --git a/env/server.ts b/env/server.ts index 738feb01f..4628866d0 100644 --- a/env/server.ts +++ b/env/server.ts @@ -22,6 +22,12 @@ export const env = createEnv({ NODE_ENV: z.enum(["development", "test", "production"]), PRINT_QUERY: z.boolean().default(false), REVALIDATE_SECRET: z.string(), + SEAMLESS_LOGIN_DA: z.string(), + SEAMLESS_LOGIN_DE: z.string(), + SEAMLESS_LOGIN_EN: z.string(), + SEAMLESS_LOGIN_FI: z.string(), + SEAMLESS_LOGIN_NO: z.string(), + SEAMLESS_LOGIN_SV: z.string(), WEBVIEW_ENCRYPTION_KEY: z.string(), }, emptyStringAsUndefined: true, @@ -45,6 +51,12 @@ export const env = createEnv({ NODE_ENV: process.env.NODE_ENV, PRINT_QUERY: process.env.PRINT_QUERY, REVALIDATE_SECRET: process.env.REVALIDATE_SECRET, + SEAMLESS_LOGIN_DA: process.env.SEAMLESS_LOGIN_DA, + SEAMLESS_LOGIN_DE: process.env.SEAMLESS_LOGIN_DE, + SEAMLESS_LOGIN_EN: process.env.SEAMLESS_LOGIN_EN, + SEAMLESS_LOGIN_FI: process.env.SEAMLESS_LOGIN_FI, + SEAMLESS_LOGIN_NO: process.env.SEAMLESS_LOGIN_NO, + SEAMLESS_LOGIN_SV: process.env.SEAMLESS_LOGIN_SV, WEBVIEW_ENCRYPTION_KEY: process.env.WEBVIEW_ENCRYPTION_KEY, }, }) diff --git a/middlewares/currentWebLogin.ts b/middlewares/currentWebLogin.ts index 6a9751183..be95c440f 100644 --- a/middlewares/currentWebLogin.ts +++ b/middlewares/currentWebLogin.ts @@ -8,16 +8,16 @@ import type { NextMiddleware } from "next/server" import type { MiddlewareMatcher } from "@/types/middleware" export const middleware: NextMiddleware = (request) => { - const redirectTo = request.nextUrl.searchParams.get("returnurl") + const returnUrl = request.nextUrl.searchParams.get("returnurl") - if (!redirectTo) { + if (!returnUrl) { return badRequest() } const lang = findLang(request.nextUrl.pathname)! const headers = new Headers(request.headers) - headers.set("x-redirect-to", redirectTo) + headers.set("x-returnurl", returnUrl) return NextResponse.rewrite(new URL(`/${lang}/login`, request.nextUrl), { request: {