feat(WEB-132): add seamless login flow
This commit is contained in:
@@ -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="
|
||||
|
||||
@@ -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 {
|
||||
/**
|
||||
|
||||
6
auth.ts
6
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
|
||||
|
||||
12
env/server.ts
vendored
12
env/server.ts
vendored
@@ -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,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user