feat(WEB-132): add seamless login flow

This commit is contained in:
Michael Zetterberg
2024-04-10 12:48:44 +02:00
parent 7093a0b2dd
commit 7be4766c00
5 changed files with 71 additions and 10 deletions

View File

@@ -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="

View File

@@ -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 {
/**

View File

@@ -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

12
env/server.ts vendored
View File

@@ -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,
},
})

View File

@@ -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: {