From 9d98a93e3ad8b158eb5a8e4c31c0820705f36be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Fri, 24 May 2024 14:32:48 +0200 Subject: [PATCH 1/9] fix: update middleware matcher to pathname includes --- middlewares/currentWebLogout.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middlewares/currentWebLogout.ts b/middlewares/currentWebLogout.ts index 8dacd770a..cae23c462 100644 --- a/middlewares/currentWebLogout.ts +++ b/middlewares/currentWebLogout.ts @@ -18,5 +18,5 @@ export const middleware: NextMiddleware = (request) => { } export const matcher: MiddlewareMatcher = (request) => { - return request.nextUrl.pathname.endsWith("/updatelogout") + return request.nextUrl.pathname.includes("/updatelogout") } From b9c642a35bae60916f0cfce977326058c50f73f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Fri, 24 May 2024 14:36:10 +0200 Subject: [PATCH 2/9] fix: remove returnurl since not used, remove double redirect when request coming from current web --- app/[lang]/(live)/(protected)/logout/route.ts | 90 ++++++++----------- 1 file changed, 35 insertions(+), 55 deletions(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 23ae2ffc0..2cf84728c 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -14,66 +14,46 @@ export async function GET( context: { params: { lang: Lang } } ) { let redirectHeaders: Headers | undefined = undefined - let redirectTo: string + let redirectTo: string = "" - const returnUrl = request.headers.get("x-returnurl") - - if (returnUrl) { - redirectTo = returnUrl - } else { - // Normal logout request from New web - redirectTo = - request.cookies.get("redirectTo")?.value || // Cookie gets set by authRequired middleware - request.nextUrl.searchParams.get("redirectTo") || - "/" - - // Make relative URL to absolute URL - if (redirectTo.startsWith("/")) { - if (!env.PUBLIC_URL) { - throw internalServerError("No value for env.PUBLIC_URL") - } - redirectTo = new URL(redirectTo, env.PUBLIC_URL).href + try { + // Initiate the seamless logout flow + let redirectUrlValue + switch (context.params.lang) { + case Lang.da: + redirectUrlValue = env.SEAMLESS_LOGOUT_DA + break + case Lang.de: + redirectUrlValue = env.SEAMLESS_LOGOUT_DE + break + case Lang.en: + redirectUrlValue = env.SEAMLESS_LOGOUT_EN + break + case Lang.fi: + redirectUrlValue = env.SEAMLESS_LOGOUT_FI + break + case Lang.no: + redirectUrlValue = env.SEAMLESS_LOGOUT_NO + break + case Lang.sv: + redirectUrlValue = env.SEAMLESS_LOGOUT_SV + break } - // 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 { - // Initiate the seamless logout flow - let redirectUrlValue - switch (context.params.lang) { - case Lang.da: - redirectUrlValue = env.SEAMLESS_LOGOUT_DA - break - case Lang.de: - redirectUrlValue = env.SEAMLESS_LOGOUT_DE - break - case Lang.en: - redirectUrlValue = env.SEAMLESS_LOGOUT_EN - break - case Lang.fi: - redirectUrlValue = env.SEAMLESS_LOGOUT_FI - break - case Lang.no: - redirectUrlValue = env.SEAMLESS_LOGOUT_NO - break - case Lang.sv: - redirectUrlValue = env.SEAMLESS_LOGOUT_SV - break - } - const redirectUrl = new URL(redirectUrlValue) - redirectUrl.searchParams.set("returnurl", redirectTo) + const redirectUrl = new URL(redirectUrlValue) + if (request.nextUrl.searchParams.get("currentweb") != null) { + // Request coming from NEW web, redirect to current web logout redirectTo = redirectUrl.toString() - } catch (e) { - console.error( - "Unable to create URL for seamless logout, proceeding without it." - ) - console.error(e) + } else { + // Request coming from CURRENT web, redirect to current web start page + redirectTo = redirectUrl.origin } + } catch (e) { + console.error( + "Unable to create URL for seamless logout, proceeding without it." + ) + console.error(e) } + try { /** * Passing `redirect: false` to `signOut` will return a result object From 6e94d28073e8d2b62070c548cb5796e99f1efebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Fri, 24 May 2024 15:03:01 +0200 Subject: [PATCH 3/9] fix: add back clean cookie --- app/[lang]/(live)/(protected)/logout/route.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 2cf84728c..40a45a91b 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -16,6 +16,12 @@ export async function GET( let redirectHeaders: Headers | undefined = undefined let redirectTo: string = "" + // 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 { // Initiate the seamless logout flow let redirectUrlValue From 9c1a24835df3a185dba8d2ae994941b731fc0473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Mon, 27 May 2024 13:53:52 +0200 Subject: [PATCH 4/9] fix: switching null check --- app/[lang]/(live)/(protected)/logout/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 40a45a91b..00520e1d6 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -46,7 +46,7 @@ export async function GET( break } const redirectUrl = new URL(redirectUrlValue) - if (request.nextUrl.searchParams.get("currentweb") != null) { + if (request.nextUrl.searchParams.get("currentweb") == null) { // Request coming from NEW web, redirect to current web logout redirectTo = redirectUrl.toString() } else { From 956178e6f22f0d5422e3e936debd65910dcb8d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Tue, 28 May 2024 13:35:04 +0200 Subject: [PATCH 5/9] chore: add redirect to Curity logout endpoint --- app/[lang]/(live)/(protected)/logout/route.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 00520e1d6..77fd98b84 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -82,8 +82,11 @@ export async function GET( console.log({ logout_signOutURL: signOutURL }) + // Redirect to Curity logout + const curityLogoutUrl = `${env.CURITY_ISSUER_USER}/authn/authenticate/logout?redirect_uri=${redirectTo}` + const redirectUrlObj = await signOut({ - redirectTo, + redirectTo: curityLogoutUrl, redirect: false, }) From 3ebe79b3c5ca5cb92e6ce86c6146244360dda6f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Tue, 28 May 2024 14:17:15 +0200 Subject: [PATCH 6/9] refactor: update logging --- app/[lang]/(live)/(protected)/logout/route.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 77fd98b84..95163b95d 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -69,8 +69,6 @@ export async function GET( console.log({ logout_NEXTAUTH_URL: process.env.NEXTAUTH_URL }) console.log({ logout_env: process.env }) - console.log({ logout_redirectTo: redirectTo }) - const headers = new Headers(nextHeaders()) const signOutURL = createActionURL( "signout", @@ -85,6 +83,8 @@ export async function GET( // Redirect to Curity logout const curityLogoutUrl = `${env.CURITY_ISSUER_USER}/authn/authenticate/logout?redirect_uri=${redirectTo}` + console.log({ logout_redirectTo: curityLogoutUrl }) + const redirectUrlObj = await signOut({ redirectTo: curityLogoutUrl, redirect: false, From 6211eda35358c745fbc71a7fadc507b174d6f0ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Thu, 30 May 2024 14:21:39 +0200 Subject: [PATCH 7/9] fix: remove clean up cookie --- app/[lang]/(live)/(protected)/logout/route.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 95163b95d..489f36857 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -13,15 +13,8 @@ export async function GET( request: NextRequest, context: { params: { lang: Lang } } ) { - let redirectHeaders: Headers | undefined = undefined let redirectTo: string = "" - // 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 { // Initiate the seamless logout flow let redirectUrlValue @@ -91,9 +84,7 @@ export async function GET( }) if (redirectUrlObj) { - return NextResponse.redirect(redirectUrlObj.redirect, { - headers: redirectHeaders, - }) + return NextResponse.redirect(redirectUrlObj.redirect) } } catch (error) { if (error instanceof AuthError) { From 0ab35679f867d259926e66bd4324355072c1b25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Thu, 30 May 2024 17:04:41 +0200 Subject: [PATCH 8/9] fix: move logic to middleware --- app/[lang]/(live)/(protected)/logout/route.ts | 69 ++++++++++--------- middlewares/currentWebLogout.ts | 24 +++++-- 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 489f36857..d29ac6571 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -15,42 +15,43 @@ export async function GET( ) { let redirectTo: string = "" - try { - // Initiate the seamless logout flow - let redirectUrlValue - switch (context.params.lang) { - case Lang.da: - redirectUrlValue = env.SEAMLESS_LOGOUT_DA - break - case Lang.de: - redirectUrlValue = env.SEAMLESS_LOGOUT_DE - break - case Lang.en: - redirectUrlValue = env.SEAMLESS_LOGOUT_EN - break - case Lang.fi: - redirectUrlValue = env.SEAMLESS_LOGOUT_FI - break - case Lang.no: - redirectUrlValue = env.SEAMLESS_LOGOUT_NO - break - case Lang.sv: - redirectUrlValue = env.SEAMLESS_LOGOUT_SV - break - } - const redirectUrl = new URL(redirectUrlValue) - if (request.nextUrl.searchParams.get("currentweb") == null) { - // Request coming from NEW web, redirect to current web logout + const returnUrl = request.headers.get("x-returnurl") + + if (returnUrl) { + // Seamless logout request from Current web + redirectTo = returnUrl + } else { + try { + // Initiate the seamless logout flow + let redirectUrlValue + switch (context.params.lang) { + case Lang.da: + redirectUrlValue = env.SEAMLESS_LOGOUT_DA + break + case Lang.de: + redirectUrlValue = env.SEAMLESS_LOGOUT_DE + break + case Lang.en: + redirectUrlValue = env.SEAMLESS_LOGOUT_EN + break + case Lang.fi: + redirectUrlValue = env.SEAMLESS_LOGOUT_FI + break + case Lang.no: + redirectUrlValue = env.SEAMLESS_LOGOUT_NO + break + case Lang.sv: + redirectUrlValue = env.SEAMLESS_LOGOUT_SV + break + } + const redirectUrl = new URL(redirectUrlValue) redirectTo = redirectUrl.toString() - } else { - // Request coming from CURRENT web, redirect to current web start page - redirectTo = redirectUrl.origin + } catch (e) { + console.error( + "Unable to create URL for seamless logout, proceeding without it." + ) + console.error(e) } - } catch (e) { - console.error( - "Unable to create URL for seamless logout, proceeding without it." - ) - console.error(e) } try { diff --git a/middlewares/currentWebLogout.ts b/middlewares/currentWebLogout.ts index cae23c462..51a1ebf83 100644 --- a/middlewares/currentWebLogout.ts +++ b/middlewares/currentWebLogout.ts @@ -1,7 +1,8 @@ import { NextResponse } from "next/server" -import { findLang } from "@/constants/languages" -import { badRequest } from "@/server/errors/next" +import { findLang, Lang } from "@/constants/languages" +import { env } from "@/env/server" +import { badRequest, internalServerError } from "@/server/errors/next" import type { NextMiddleware } from "next/server" @@ -14,9 +15,20 @@ export const middleware: NextMiddleware = (request) => { } const lang = findLang(request.nextUrl.pathname)! - return NextResponse.rewrite(new URL(`/${lang}/logout`, request.nextUrl)) -} + if (!env.PUBLIC_URL) { + throw internalServerError("No value for env.PUBLIC_URL") + } + const redirectTo = env.PUBLIC_URL -export const matcher: MiddlewareMatcher = (request) => { - return request.nextUrl.pathname.includes("/updatelogout") + const headers = new Headers(request.headers) + headers.set("x-returnurl", redirectTo) + + return NextResponse.rewrite(new URL(`/${lang}/logout`, request.nextUrl), { + request: { + headers, + }, + }) +} +export const matcher: MiddlewareMatcher = (request) => { + return request.nextUrl.pathname.endsWith("/updatelogout") } From 1e319fb7564f7fd39d126a02976fe5d03ec3a8e5 Mon Sep 17 00:00:00 2001 From: Michael Zetterberg Date: Fri, 31 May 2024 08:41:34 +0200 Subject: [PATCH 9/9] fix: encode redirect url --- app/[lang]/(live)/(protected)/logout/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index d29ac6571..38b98361a 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -75,7 +75,7 @@ export async function GET( console.log({ logout_signOutURL: signOutURL }) // Redirect to Curity logout - const curityLogoutUrl = `${env.CURITY_ISSUER_USER}/authn/authenticate/logout?redirect_uri=${redirectTo}` + const curityLogoutUrl = `${env.CURITY_ISSUER_USER}/authn/authenticate/logout?redirect_uri=${encodeURIComponent(redirectTo)}` console.log({ logout_redirectTo: curityLogoutUrl })