From 5c3a57c43a89cb6ce7673e46f41a180e5c3027a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Tue, 14 May 2024 08:51:31 +0200 Subject: [PATCH 01/18] chore: add invalidateSessions endpoint and query --- lib/api/endpoints.ts | 1 + server/routers/user/query.ts | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/lib/api/endpoints.ts b/lib/api/endpoints.ts index 2efc39cd8..b4f8f4761 100644 --- a/lib/api/endpoints.ts +++ b/lib/api/endpoints.ts @@ -9,6 +9,7 @@ export namespace endpoints { profile = "profile/v1/Profile", upcomingStays = "booking/v1/Stays/future", previousStays = "booking/v1/Stays/past", + invalidateSessions = "profile/v1/Profile/invalidateSessions", } } diff --git a/server/routers/user/query.ts b/server/routers/user/query.ts index 3f8efdedc..124ca56b5 100644 --- a/server/routers/user/query.ts +++ b/server/routers/user/query.ts @@ -21,6 +21,36 @@ function fakingRequest(payload: T): Promise { } export const userQueryRouter = router({ + invalidateSessions: protectedProcedure.query(async function ({ ctx }) { + try { + const apiResponse = await api.post(api.endpoints.v1.invalidateSessions, { + cache: "no-store", + headers: { + Authorization: `Bearer ${ctx.session.token.access_token}`, + }, + body: {}, + }) + + if (!apiResponse.ok) { + switch (apiResponse.status) { + case 400: + throw badRequestError(apiResponse) + case 401: + throw unauthorizedError(apiResponse) + case 403: + throw forbiddenError(apiResponse) + default: + throw internalServerError(apiResponse) + } + } + return true + } catch (error) { + console.info(`Invalidate Sessions Error`) + console.error(error) + throw internalServerError() + } + }), + get: protectedProcedure.query(async function ({ ctx }) { const apiResponse = await api.get(api.endpoints.v1.profile, { cache: "no-store", From 02107784ad9e5e242210355681a459ed19be320e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Tue, 14 May 2024 15:00:29 +0200 Subject: [PATCH 02/18] chore: add temp env endpoint for seamless logout --- .env.local.example | 8 +++++++- env/server.ts | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/.env.local.example b/.env.local.example index c1e013b50..8f97d39e3 100644 --- a/.env.local.example +++ b/.env.local.example @@ -19,10 +19,16 @@ NEXTAUTH_REDIRECT_PROXY_URL="http://localhost:3000/api/web/auth" NEXTAUTH_SECRET="" # NEXTAUTH_URL="DO NOT SET THIS HERE, it is managed in next.config.js" REVALIDATE_SECRET="" +WEBVIEW_ENCRYPTION_KEY="MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=" 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_SV="http://www.example.se/updatelogin" -WEBVIEW_ENCRYPTION_KEY="MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=" +SEAMLESS_LOGOUT_DA="http://www.example.dk/TBD" +SEAMLESS_LOGOUT_DE="http://www.example.de/TBD" +SEAMLESS_LOGOUT_EN="http://www.example.com/TBD" +SEAMLESS_LOGOUT_FI="http://www.example.fi/TBD" +SEAMLESS_LOGOUT_NO="http://www.example.no/TBD" +SEAMLESS_LOGOUT_SV="http://www.example.se/TBD" diff --git a/env/server.ts b/env/server.ts index e3a7e1ea8..c766e0bed 100644 --- a/env/server.ts +++ b/env/server.ts @@ -48,6 +48,13 @@ export const env = createEnv({ SEAMLESS_LOGIN_FI: z.string(), SEAMLESS_LOGIN_NO: z.string(), SEAMLESS_LOGIN_SV: z.string(), + SEAMLESS_LOGOUT_DA: z.string(), + SEAMLESS_LOGOUT_DE: z.string(), + SEAMLESS_LOGOUT_EN: z.string(), + SEAMLESS_LOGOUT_FI: z.string(), + SEAMLESS_LOGOUT_NO: z.string(), + SEAMLESS_LOGOUT_SV: z.string(), + URL: z.string().optional(), WEBVIEW_ENCRYPTION_KEY: z.string(), }, emptyStringAsUndefined: true, @@ -82,6 +89,13 @@ export const env = createEnv({ SEAMLESS_LOGIN_FI: process.env.SEAMLESS_LOGIN_FI, SEAMLESS_LOGIN_NO: process.env.SEAMLESS_LOGIN_NO, SEAMLESS_LOGIN_SV: process.env.SEAMLESS_LOGIN_SV, + SEAMLESS_LOGOUT_DA: process.env.SEAMLESS_LOGOUT_DA, + SEAMLESS_LOGOUT_DE: process.env.SEAMLESS_LOGOUT_DE, + SEAMLESS_LOGOUT_EN: process.env.SEAMLESS_LOGOUT_EN, + SEAMLESS_LOGOUT_FI: process.env.SEAMLESS_LOGOUT_FI, + SEAMLESS_LOGOUT_NO: process.env.SEAMLESS_LOGOUT_NO, + SEAMLESS_LOGOUT_SV: process.env.SEAMLESS_LOGOUT_SV, + URL: process.env.URL, WEBVIEW_ENCRYPTION_KEY: process.env.WEBVIEW_ENCRYPTION_KEY, }, }) From 1777ed02055ce87779529d361b1e5908c4619d62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Tue, 14 May 2024 15:01:06 +0200 Subject: [PATCH 03/18] chore: update logout route as login --- app/[lang]/(live)/(protected)/logout/route.ts | 108 ++++++++++++++++-- auth.ts | 5 + 2 files changed, 103 insertions(+), 10 deletions(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 336613db0..003602043 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -1,32 +1,120 @@ +import { createActionURL } from "@auth/core" +import { headers as nextHeaders } from "next/headers" import { NextRequest, NextResponse } from "next/server" import { AuthError } from "next-auth" +import { Lang } from "@/constants/languages" +import { env } from "@/env/server" +import { serverClient } from "@/lib/trpc/server" import { badRequest } from "@/server/errors/next" import { signOut } from "@/auth" -export async function GET(request: NextRequest) { - const returnUrl = request.headers.get("x-returnurl") +export async function GET( + request: NextRequest, + context: { params: { lang: Lang } } +) { + let redirectHeaders: Headers | undefined = undefined + let redirectTo: string - // If all else fails, always redirect to startpage - const redirectTo = - returnUrl || - request.nextUrl.searchParams.get("redirectTo") || - "/" + const returnUrl = request.headers.get("x-returnurl") + if (returnUrl) { + // Seamless logout request from Current web + redirectTo = returnUrl + } else { + // Normal logout request from New web + redirectTo = + request.cookies.get("redirectTo")?.value || // Cookie gets set by authRequired middleware + request.headers.get("x-redirect-to") || + request.nextUrl.searchParams.get("redirectTo") || + request.headers.get("Referer") || + "/" + console.log(redirectTo) + // If above fails, always redirect to startpage + if (!redirectTo) { + const proto = request.headers.get("x-forwarded-proto") ?? "http" + const host = + request.headers.get("x-forwarded-host") ?? + request.headers.get("host") ?? + env.URL + redirectTo = `${proto}://${host}/` + console.log({ logout_fallback: 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" + ) + } try { + // Initiate the seamless logout flow + const invalidateResponse = await serverClient().user.invalidateSessions() + + let redirectUrlValue + console.log(context.params.lang) + 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) + redirectTo = redirectUrl.toString() + console.log(redirectUrl, redirectTo) + } catch (e) { + console.error( + "Unable to create URL for seamless logout, proceeding without it." + ) + console.error(e) + } + try { + console.log({ logout_AUTH_URL: process.env.AUTH_URL }) + console.log({ logout_NEXTAUTH_URL: process.env.NEXTAUTH_URL }) + console.log({ logout_env: process.env }) + /** * Passing `redirect: false` to `signOut` will return a result object * instead of automatically redirecting inside of `signOut`. * https://github.com/nextauthjs/next-auth/blob/3c035ec/packages/next-auth/src/lib/actions.ts#L104 */ - const obj = await signOut({ + const headers = new Headers(nextHeaders()) + const signOutURL = createActionURL( + "signout", + // @ts-expect-error `x-forwarded-proto` is not nullable, next.js sets it by default + headers.get("x-forwarded-proto"), + headers, + process.env + ) + + console.log({ logout_signInURL: signOutURL }) + + const redirectUrl = await signOut({ redirectTo, redirect: false, }) - if (obj) { - return NextResponse.redirect(obj.redirect) + if (redirectUrl) { + return NextResponse.redirect(redirectUrl, { + headers: redirectHeaders, + }) } } catch (error) { if (error instanceof AuthError) { diff --git a/auth.ts b/auth.ts index 59e85c82d..778824aea 100644 --- a/auth.ts +++ b/auth.ts @@ -152,6 +152,11 @@ export const config = { // console.log(arguments) // console.log("#### END - SIGNIN EVENT ARGS ######") // }, + // async signOut() { + // console.log("#### SIGNOUT EVENT ARGS ######") + // console.log(arguments) + // console.log("#### END - SIGNOUT EVENT ARGS ######") + // }, // async session() { // console.log("#### SESSION EVENT ARGS ######") // console.log(arguments) From a43754d624e40cb9333f6fb62401aa983884a6f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Tue, 14 May 2024 15:09:02 +0200 Subject: [PATCH 04/18] chore: change sidebar logout href --- components/MyPages/Sidebar/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/MyPages/Sidebar/index.tsx b/components/MyPages/Sidebar/index.tsx index 4bcae43b8..96da22154 100644 --- a/components/MyPages/Sidebar/index.tsx +++ b/components/MyPages/Sidebar/index.tsx @@ -1,6 +1,7 @@ import { Fragment } from "react" import { LogOut } from "react-feather" +import { logout } from "@/constants/routes/handleAuth" import { serverClient } from "@/lib/trpc/server" import Link from "@/components/TempDesignSystem/Link" @@ -41,7 +42,7 @@ export default async function Sidebar() { ))} - + Log out From 74ff37008d390290062faf5bee4c69470a4c13b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Tue, 14 May 2024 15:23:21 +0200 Subject: [PATCH 05/18] temp --- app/[lang]/(live)/(public)/login/route.ts | 4 ++-- middlewares/authRequired.ts | 2 +- middlewares/webView.ts | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/[lang]/(live)/(public)/login/route.ts b/app/[lang]/(live)/(public)/login/route.ts index 006c8af9e..16447022c 100644 --- a/app/[lang]/(live)/(public)/login/route.ts +++ b/app/[lang]/(live)/(public)/login/route.ts @@ -15,6 +15,7 @@ export async function GET( let redirectTo: string const returnUrl = request.headers.get("x-returnurl") + console.log("TESTTEST", returnUrl, request) if (returnUrl) { // Seamless login request from Current web redirectTo = returnUrl @@ -32,7 +33,6 @@ export async function GET( } redirectTo = new URL(redirectTo, env.PUBLIC_URL).href } - // Clean up cookie from authRequired middleware redirectHeaders = new Headers() redirectHeaders.append( @@ -94,7 +94,7 @@ export async function GET( ui_locales: context.params.lang, } ) - + console.log(redirectUrl) if (redirectUrl) { return NextResponse.redirect(redirectUrl, { headers: redirectHeaders, diff --git a/middlewares/authRequired.ts b/middlewares/authRequired.ts index 268316d41..d0a65c215 100644 --- a/middlewares/authRequired.ts +++ b/middlewares/authRequired.ts @@ -40,7 +40,7 @@ import type { MiddlewareMatcher } from "@/types/middleware" export const middleware = auth(async (request) => { const { nextUrl } = request const lang = findLang(nextUrl.pathname)! - + console.log("TestTest ", nextUrl) const isLoggedIn = !!request.auth const hasError = request.auth?.error diff --git a/middlewares/webView.ts b/middlewares/webView.ts index 99dcbec28..7b6fadee6 100644 --- a/middlewares/webView.ts +++ b/middlewares/webView.ts @@ -1,8 +1,9 @@ -import { NextResponse, type NextMiddleware } from "next/server" +import { type NextMiddleware, NextResponse } from "next/server" import { findLang } from "@/constants/languages" import { env } from "@/env/server" import { badRequest, internalServerError } from "@/server/errors/next" + import { decryptData } from "@/utils/aes" import type { MiddlewareMatcher } from "@/types/middleware" From 3ba78986daff409d667ece8c8b9a0153a080d819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Wed, 15 May 2024 13:51:40 +0200 Subject: [PATCH 06/18] fix: temp logs --- app/[lang]/(live)/(protected)/logout/route.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 003602043..19587478c 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -53,7 +53,7 @@ export async function GET( const invalidateResponse = await serverClient().user.invalidateSessions() let redirectUrlValue - console.log(context.params.lang) + switch (context.params.lang) { case Lang.da: redirectUrlValue = env.SEAMLESS_LOGOUT_DA @@ -74,7 +74,7 @@ export async function GET( redirectUrlValue = env.SEAMLESS_LOGOUT_SV break } - + console.log(redirectUrlValue) const redirectUrl = new URL(redirectUrlValue) redirectUrl.searchParams.set("returnurl", redirectTo) redirectTo = redirectUrl.toString() @@ -104,15 +104,15 @@ export async function GET( process.env ) - console.log({ logout_signInURL: signOutURL }) + console.log({ logout_signOutURL: signOutURL }) - const redirectUrl = await signOut({ + const redirectUrlObj = await signOut({ redirectTo, redirect: false, }) - - if (redirectUrl) { - return NextResponse.redirect(redirectUrl, { + console.log(redirectUrlObj) + if (redirectUrlObj) { + return NextResponse.redirect(redirectUrlObj.redirect, { headers: redirectHeaders, }) } From af1d65f4bbfe7bca94de221452dd104f0c01bc4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Tue, 21 May 2024 12:02:23 +0200 Subject: [PATCH 07/18] chore: add new endpoint for logout from current web --- .env.local.example | 7 +- app/[lang]/(live)/(protected)/logout/route.ts | 86 ++++++------------- env/server.ts | 14 +-- 3 files changed, 30 insertions(+), 77 deletions(-) diff --git a/.env.local.example b/.env.local.example index 8f97d39e3..05ebae40e 100644 --- a/.env.local.example +++ b/.env.local.example @@ -26,9 +26,4 @@ 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_SV="http://www.example.se/updatelogin" -SEAMLESS_LOGOUT_DA="http://www.example.dk/TBD" -SEAMLESS_LOGOUT_DE="http://www.example.de/TBD" -SEAMLESS_LOGOUT_EN="http://www.example.com/TBD" -SEAMLESS_LOGOUT_FI="http://www.example.fi/TBD" -SEAMLESS_LOGOUT_NO="http://www.example.no/TBD" -SEAMLESS_LOGOUT_SV="http://www.example.se/TBD" +SEAMLESS_LOGOUT="http://www.example.com/updatelogout?newweb" diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 19587478c..b7d80d95b 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -3,42 +3,33 @@ import { headers as nextHeaders } from "next/headers" import { NextRequest, NextResponse } from "next/server" import { AuthError } from "next-auth" -import { Lang } from "@/constants/languages" import { env } from "@/env/server" import { serverClient } from "@/lib/trpc/server" -import { badRequest } from "@/server/errors/next" +import { internalServerError } from "@/server/errors/next" import { signOut } from "@/auth" -export async function GET( - request: NextRequest, - context: { params: { lang: Lang } } -) { +export async function GET(request: NextRequest) { let redirectHeaders: Headers | undefined = undefined let redirectTo: string const returnUrl = request.headers.get("x-returnurl") if (returnUrl) { - // Seamless logout request from Current web + // Should check for ?currentweb in header? redirectTo = returnUrl } else { // Normal logout request from New web redirectTo = request.cookies.get("redirectTo")?.value || // Cookie gets set by authRequired middleware - request.headers.get("x-redirect-to") || request.nextUrl.searchParams.get("redirectTo") || - request.headers.get("Referer") || "/" - console.log(redirectTo) + // If above fails, always redirect to startpage - if (!redirectTo) { - const proto = request.headers.get("x-forwarded-proto") ?? "http" - const host = - request.headers.get("x-forwarded-host") ?? - request.headers.get("host") ?? - env.URL - redirectTo = `${proto}://${host}/` - console.log({ logout_fallback: redirectTo }) + if (redirectTo.startsWith("/")) { + if (!env.PUBLIC_URL) { + throw internalServerError("No value for env.PUBLIC_URL") + } + redirectTo = new URL(redirectTo, env.PUBLIC_URL).href } // Clean up cookie from authRequired middleware redirectHeaders = new Headers() @@ -46,55 +37,32 @@ export async function GET( "set-cookie", "redirectTo=; Expires=Thu, 01 Jan 1970 00:00:00 UTC; Path=/; HttpOnly; SameSite=Lax" ) - } - try { - // Initiate the seamless logout flow - const invalidateResponse = await serverClient().user.invalidateSessions() + try { + // Initiate the seamless logout flow + const invalidateResponse = await serverClient().user.invalidateSessions() - 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(env.SEAMLESS_LOGOUT) + redirectUrl.searchParams.set("returnurl", redirectTo) + redirectTo = redirectUrl.toString() + } catch (e) { + console.error( + "Unable to create URL for seamless logout, proceeding without it." + ) + console.error(e) } - console.log(redirectUrlValue) - const redirectUrl = new URL(redirectUrlValue) - redirectUrl.searchParams.set("returnurl", redirectTo) - redirectTo = redirectUrl.toString() - console.log(redirectUrl, redirectTo) - } catch (e) { - console.error( - "Unable to create URL for seamless logout, proceeding without it." - ) - console.error(e) } try { - console.log({ logout_AUTH_URL: process.env.AUTH_URL }) - console.log({ logout_NEXTAUTH_URL: process.env.NEXTAUTH_URL }) - console.log({ logout_env: process.env }) - /** * Passing `redirect: false` to `signOut` will return a result object * instead of automatically redirecting inside of `signOut`. * https://github.com/nextauthjs/next-auth/blob/3c035ec/packages/next-auth/src/lib/actions.ts#L104 */ + 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", @@ -110,7 +78,7 @@ export async function GET( redirectTo, redirect: false, }) - console.log(redirectUrlObj) + if (redirectUrlObj) { return NextResponse.redirect(redirectUrlObj.redirect, { headers: redirectHeaders, @@ -124,5 +92,5 @@ export async function GET( } } - return badRequest() + return internalServerError() } diff --git a/env/server.ts b/env/server.ts index c766e0bed..db7091728 100644 --- a/env/server.ts +++ b/env/server.ts @@ -48,12 +48,7 @@ export const env = createEnv({ SEAMLESS_LOGIN_FI: z.string(), SEAMLESS_LOGIN_NO: z.string(), SEAMLESS_LOGIN_SV: z.string(), - SEAMLESS_LOGOUT_DA: z.string(), - SEAMLESS_LOGOUT_DE: z.string(), - SEAMLESS_LOGOUT_EN: z.string(), - SEAMLESS_LOGOUT_FI: z.string(), - SEAMLESS_LOGOUT_NO: z.string(), - SEAMLESS_LOGOUT_SV: z.string(), + SEAMLESS_LOGOUT: z.string(), URL: z.string().optional(), WEBVIEW_ENCRYPTION_KEY: z.string(), }, @@ -89,12 +84,7 @@ export const env = createEnv({ SEAMLESS_LOGIN_FI: process.env.SEAMLESS_LOGIN_FI, SEAMLESS_LOGIN_NO: process.env.SEAMLESS_LOGIN_NO, SEAMLESS_LOGIN_SV: process.env.SEAMLESS_LOGIN_SV, - SEAMLESS_LOGOUT_DA: process.env.SEAMLESS_LOGOUT_DA, - SEAMLESS_LOGOUT_DE: process.env.SEAMLESS_LOGOUT_DE, - SEAMLESS_LOGOUT_EN: process.env.SEAMLESS_LOGOUT_EN, - SEAMLESS_LOGOUT_FI: process.env.SEAMLESS_LOGOUT_FI, - SEAMLESS_LOGOUT_NO: process.env.SEAMLESS_LOGOUT_NO, - SEAMLESS_LOGOUT_SV: process.env.SEAMLESS_LOGOUT_SV, + SEAMLESS_LOGOUT: process.env.SEAMLESS_LOGOUT, URL: process.env.URL, WEBVIEW_ENCRYPTION_KEY: process.env.WEBVIEW_ENCRYPTION_KEY, }, From 3085cccf8b1d170f26bb2036af388e2834a86ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Tue, 21 May 2024 12:07:45 +0200 Subject: [PATCH 08/18] chore: add lang for logout href --- app/[lang]/(live)/(protected)/my-pages/[...path]/page.tsx | 2 +- components/MyPages/Sidebar/index.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/[lang]/(live)/(protected)/my-pages/[...path]/page.tsx b/app/[lang]/(live)/(protected)/my-pages/[...path]/page.tsx index 3c1ce9f98..d8a292e62 100644 --- a/app/[lang]/(live)/(protected)/my-pages/[...path]/page.tsx +++ b/app/[lang]/(live)/(protected)/my-pages/[...path]/page.tsx @@ -20,7 +20,7 @@ export default async function MyPages({
- + {accountPage.content.length ? ( diff --git a/components/MyPages/Sidebar/index.tsx b/components/MyPages/Sidebar/index.tsx index 96da22154..379786cad 100644 --- a/components/MyPages/Sidebar/index.tsx +++ b/components/MyPages/Sidebar/index.tsx @@ -9,7 +9,9 @@ import Title from "@/components/Title" import styles from "./sidebar.module.css" -export default async function Sidebar() { +import { LangParams } from "@/types/params" + +export default async function Sidebar(params: LangParams) { const navigation = await serverClient().contentstack.myPages.navigation.get() return ( @@ -42,7 +44,7 @@ export default async function Sidebar() { ))} - + Log out From d521f9fe27ba0b628681be2ff1e07d63a30a76b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Tue, 21 May 2024 12:29:45 +0200 Subject: [PATCH 09/18] fix: remove code from rebase --- env/server.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/env/server.ts b/env/server.ts index db7091728..04eeabf62 100644 --- a/env/server.ts +++ b/env/server.ts @@ -49,7 +49,6 @@ export const env = createEnv({ SEAMLESS_LOGIN_NO: z.string(), SEAMLESS_LOGIN_SV: z.string(), SEAMLESS_LOGOUT: z.string(), - URL: z.string().optional(), WEBVIEW_ENCRYPTION_KEY: z.string(), }, emptyStringAsUndefined: true, @@ -85,7 +84,6 @@ export const env = createEnv({ SEAMLESS_LOGIN_NO: process.env.SEAMLESS_LOGIN_NO, SEAMLESS_LOGIN_SV: process.env.SEAMLESS_LOGIN_SV, SEAMLESS_LOGOUT: process.env.SEAMLESS_LOGOUT, - URL: process.env.URL, WEBVIEW_ENCRYPTION_KEY: process.env.WEBVIEW_ENCRYPTION_KEY, }, }) From 9a92e637b921862b76bd40b46a8a95bca4709eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Tue, 21 May 2024 12:33:06 +0200 Subject: [PATCH 10/18] fix: update comment --- 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 b7d80d95b..26a584e45 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -24,7 +24,7 @@ export async function GET(request: NextRequest) { request.nextUrl.searchParams.get("redirectTo") || "/" - // If above fails, always redirect to startpage + // Make relative URL to absolute URL if (redirectTo.startsWith("/")) { if (!env.PUBLIC_URL) { throw internalServerError("No value for env.PUBLIC_URL") From dec41fa4773462381f3bbb8a8b612f52db36c474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Wed, 22 May 2024 08:55:04 +0200 Subject: [PATCH 11/18] chore: add middleware for logout from current web --- middleware.ts | 2 ++ middlewares/currentWebLogout.ts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 middlewares/currentWebLogout.ts diff --git a/middleware.ts b/middleware.ts index b21ef3a30..05299b8f5 100644 --- a/middleware.ts +++ b/middleware.ts @@ -4,6 +4,7 @@ import { findLang } from "./constants/languages" import * as authRequired from "./middlewares/authRequired" import * as cmsContent from "./middlewares/cmsContent" import * as currentWebLogin from "./middlewares/currentWebLogin" +import * as currentWebLogout from "./middlewares/currentWebLogout" import * as handleAuth from "./middlewares/handleAuth" import * as myPages from "./middlewares/myPages" import * as webView from "./middlewares/webView" @@ -26,6 +27,7 @@ export const middleware: NextMiddleware = async (request, event) => { const middlewares = [ currentWebLogin, + currentWebLogout, authRequired, handleAuth, myPages, diff --git a/middlewares/currentWebLogout.ts b/middlewares/currentWebLogout.ts new file mode 100644 index 000000000..d37bd5709 --- /dev/null +++ b/middlewares/currentWebLogout.ts @@ -0,0 +1,31 @@ +import { NextResponse } from "next/server" + +import { findLang } from "@/constants/languages" +import { badRequest } from "@/server/errors/next" + +import type { NextMiddleware } from "next/server" + +import type { MiddlewareMatcher } from "@/types/middleware" + +export const middleware: NextMiddleware = (request) => { + console.log("HEJ", request) + const currentwebUrl = request.nextUrl.searchParams.get("currentweb") + if (currentwebUrl == null) { + return badRequest() + } + + const lang = findLang(request.nextUrl.pathname)! + + //const headers = new Headers(request.headers) + //headers.set("x-returnurl", returnUrl) + + return NextResponse.rewrite(new URL(`/${lang}/logout`, request.nextUrl), { + /*request: { + headers, + },*/ + }) +} + +export const matcher: MiddlewareMatcher = (request) => { + return request.nextUrl.pathname.endsWith("/updatelogout") //?currentweb") +} From eeceddc545e2ef0a75619343ffbb70a64636c88b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Wed, 22 May 2024 10:37:20 +0200 Subject: [PATCH 12/18] chore: remove invalidateSession --- app/[lang]/(live)/(protected)/logout/route.ts | 2 -- lib/api/endpoints.ts | 1 - server/routers/user/query.ts | 30 ------------------- 3 files changed, 33 deletions(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 26a584e45..55648c386 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -40,8 +40,6 @@ export async function GET(request: NextRequest) { try { // Initiate the seamless logout flow - const invalidateResponse = await serverClient().user.invalidateSessions() - const redirectUrl = new URL(env.SEAMLESS_LOGOUT) redirectUrl.searchParams.set("returnurl", redirectTo) redirectTo = redirectUrl.toString() diff --git a/lib/api/endpoints.ts b/lib/api/endpoints.ts index b4f8f4761..2efc39cd8 100644 --- a/lib/api/endpoints.ts +++ b/lib/api/endpoints.ts @@ -9,7 +9,6 @@ export namespace endpoints { profile = "profile/v1/Profile", upcomingStays = "booking/v1/Stays/future", previousStays = "booking/v1/Stays/past", - invalidateSessions = "profile/v1/Profile/invalidateSessions", } } diff --git a/server/routers/user/query.ts b/server/routers/user/query.ts index 124ca56b5..3f8efdedc 100644 --- a/server/routers/user/query.ts +++ b/server/routers/user/query.ts @@ -21,36 +21,6 @@ function fakingRequest(payload: T): Promise { } export const userQueryRouter = router({ - invalidateSessions: protectedProcedure.query(async function ({ ctx }) { - try { - const apiResponse = await api.post(api.endpoints.v1.invalidateSessions, { - cache: "no-store", - headers: { - Authorization: `Bearer ${ctx.session.token.access_token}`, - }, - body: {}, - }) - - if (!apiResponse.ok) { - switch (apiResponse.status) { - case 400: - throw badRequestError(apiResponse) - case 401: - throw unauthorizedError(apiResponse) - case 403: - throw forbiddenError(apiResponse) - default: - throw internalServerError(apiResponse) - } - } - return true - } catch (error) { - console.info(`Invalidate Sessions Error`) - console.error(error) - throw internalServerError() - } - }), - get: protectedProcedure.query(async function ({ ctx }) { const apiResponse = await api.get(api.endpoints.v1.profile, { cache: "no-store", From e65145687d74fc0f7a2c23cf3732cbc873f56fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Wed, 22 May 2024 11:03:26 +0200 Subject: [PATCH 13/18] chore: add back language specific routes --- .env.local.example | 7 +++- app/[lang]/(live)/(protected)/logout/route.ts | 32 ++++++++++++++++--- env/server.ts | 14 ++++++-- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/.env.local.example b/.env.local.example index 05ebae40e..721213c83 100644 --- a/.env.local.example +++ b/.env.local.example @@ -26,4 +26,9 @@ 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_SV="http://www.example.se/updatelogin" -SEAMLESS_LOGOUT="http://www.example.com/updatelogout?newweb" +SEAMLESS_LOGOUT_DA="http://www.example.dk/updatelogout?newweb" +SEAMLESS_LOGOUT_DE="http://www.example.de/updatelogout?newweb" +SEAMLESS_LOGOUT_EN="http://www.example.com/updatelogout?newweb" +SEAMLESS_LOGOUT_FI="http://www.example.fi/updatelogout?newweb" +SEAMLESS_LOGOUT_NO="http://www.example.no/updatelogout?newweb" +SEAMLESS_LOGOUT_SV="http://www.example.sv/updatelogout?newweb" diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 55648c386..73781abf4 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -3,19 +3,22 @@ import { headers as nextHeaders } from "next/headers" import { NextRequest, NextResponse } from "next/server" import { AuthError } from "next-auth" +import { Lang } from "@/constants/languages" import { env } from "@/env/server" -import { serverClient } from "@/lib/trpc/server" import { internalServerError } from "@/server/errors/next" import { signOut } from "@/auth" -export async function GET(request: NextRequest) { +export async function GET( + request: NextRequest, + context: { params: { lang: Lang } } +) { let redirectHeaders: Headers | undefined = undefined let redirectTo: string const returnUrl = request.headers.get("x-returnurl") + console.log("TESTING", returnUrl) if (returnUrl) { - // Should check for ?currentweb in header? redirectTo = returnUrl } else { // Normal logout request from New web @@ -40,7 +43,28 @@ export async function GET(request: NextRequest) { try { // Initiate the seamless logout flow - const redirectUrl = new URL(env.SEAMLESS_LOGOUT) + 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) redirectTo = redirectUrl.toString() } catch (e) { diff --git a/env/server.ts b/env/server.ts index 04eeabf62..7a01807d8 100644 --- a/env/server.ts +++ b/env/server.ts @@ -48,7 +48,12 @@ export const env = createEnv({ SEAMLESS_LOGIN_FI: z.string(), SEAMLESS_LOGIN_NO: z.string(), SEAMLESS_LOGIN_SV: z.string(), - SEAMLESS_LOGOUT: z.string(), + SEAMLESS_LOGOUT_DA: z.string(), + SEAMLESS_LOGOUT_DE: z.string(), + SEAMLESS_LOGOUT_EN: z.string(), + SEAMLESS_LOGOUT_FI: z.string(), + SEAMLESS_LOGOUT_NO: z.string(), + SEAMLESS_LOGOUT_SV: z.string(), WEBVIEW_ENCRYPTION_KEY: z.string(), }, emptyStringAsUndefined: true, @@ -83,7 +88,12 @@ export const env = createEnv({ SEAMLESS_LOGIN_FI: process.env.SEAMLESS_LOGIN_FI, SEAMLESS_LOGIN_NO: process.env.SEAMLESS_LOGIN_NO, SEAMLESS_LOGIN_SV: process.env.SEAMLESS_LOGIN_SV, - SEAMLESS_LOGOUT: process.env.SEAMLESS_LOGOUT, + SEAMLESS_LOGOUT_DA: process.env.SEAMLESS_LOGOUT_DA, + SEAMLESS_LOGOUT_DE: process.env.SEAMLESS_LOGOUT_DE, + SEAMLESS_LOGOUT_EN: process.env.SEAMLESS_LOGOUT_EN, + SEAMLESS_LOGOUT_FI: process.env.SEAMLESS_LOGOUT_FI, + SEAMLESS_LOGOUT_NO: process.env.SEAMLESS_LOGOUT_NO, + SEAMLESS_LOGOUT_SV: process.env.SEAMLESS_LOGOUT_SV, WEBVIEW_ENCRYPTION_KEY: process.env.WEBVIEW_ENCRYPTION_KEY, }, }) From e3e4d6c1c8371ea85dfe60a641595969a0226760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Wed, 22 May 2024 11:11:19 +0200 Subject: [PATCH 14/18] fix: cleanup logs --- app/[lang]/(live)/(protected)/logout/route.ts | 3 ++- app/[lang]/(live)/(public)/login/route.ts | 3 ++- middlewares/authRequired.ts | 2 +- middlewares/currentWebLogout.ts | 15 +++------------ 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 73781abf4..5383be38d 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -17,7 +17,7 @@ export async function GET( let redirectTo: string const returnUrl = request.headers.get("x-returnurl") - console.log("TESTING", returnUrl) + if (returnUrl) { redirectTo = returnUrl } else { @@ -67,6 +67,7 @@ export async function GET( const redirectUrl = new URL(redirectUrlValue) redirectUrl.searchParams.set("returnurl", redirectTo) redirectTo = redirectUrl.toString() + console.log("TOTO", redirectTo) } catch (e) { console.error( "Unable to create URL for seamless logout, proceeding without it." diff --git a/app/[lang]/(live)/(public)/login/route.ts b/app/[lang]/(live)/(public)/login/route.ts index 16447022c..fa9db75aa 100644 --- a/app/[lang]/(live)/(public)/login/route.ts +++ b/app/[lang]/(live)/(public)/login/route.ts @@ -15,7 +15,7 @@ export async function GET( let redirectTo: string const returnUrl = request.headers.get("x-returnurl") - console.log("TESTTEST", returnUrl, request) + if (returnUrl) { // Seamless login request from Current web redirectTo = returnUrl @@ -33,6 +33,7 @@ export async function GET( } redirectTo = new URL(redirectTo, env.PUBLIC_URL).href } + // Clean up cookie from authRequired middleware redirectHeaders = new Headers() redirectHeaders.append( diff --git a/middlewares/authRequired.ts b/middlewares/authRequired.ts index d0a65c215..268316d41 100644 --- a/middlewares/authRequired.ts +++ b/middlewares/authRequired.ts @@ -40,7 +40,7 @@ import type { MiddlewareMatcher } from "@/types/middleware" export const middleware = auth(async (request) => { const { nextUrl } = request const lang = findLang(nextUrl.pathname)! - console.log("TestTest ", nextUrl) + const isLoggedIn = !!request.auth const hasError = request.auth?.error diff --git a/middlewares/currentWebLogout.ts b/middlewares/currentWebLogout.ts index d37bd5709..8dacd770a 100644 --- a/middlewares/currentWebLogout.ts +++ b/middlewares/currentWebLogout.ts @@ -8,24 +8,15 @@ import type { NextMiddleware } from "next/server" import type { MiddlewareMatcher } from "@/types/middleware" export const middleware: NextMiddleware = (request) => { - console.log("HEJ", request) const currentwebUrl = request.nextUrl.searchParams.get("currentweb") - if (currentwebUrl == null) { + if (currentwebUrl == null || undefined) { return badRequest() } - const lang = findLang(request.nextUrl.pathname)! - //const headers = new Headers(request.headers) - //headers.set("x-returnurl", returnUrl) - - return NextResponse.rewrite(new URL(`/${lang}/logout`, request.nextUrl), { - /*request: { - headers, - },*/ - }) + return NextResponse.rewrite(new URL(`/${lang}/logout`, request.nextUrl)) } export const matcher: MiddlewareMatcher = (request) => { - return request.nextUrl.pathname.endsWith("/updatelogout") //?currentweb") + return request.nextUrl.pathname.endsWith("/updatelogout") } From 93cb38322043122a91356d6b714bd13e170296f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Wed, 22 May 2024 11:22:15 +0200 Subject: [PATCH 15/18] refactor: cleanup --- app/[lang]/(live)/(protected)/logout/route.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 5383be38d..23ae2ffc0 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -67,7 +67,6 @@ export async function GET( const redirectUrl = new URL(redirectUrlValue) redirectUrl.searchParams.set("returnurl", redirectTo) redirectTo = redirectUrl.toString() - console.log("TOTO", redirectTo) } catch (e) { console.error( "Unable to create URL for seamless logout, proceeding without it." From c35176dda89c751e35a03a014f611316e80e2e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Wed, 22 May 2024 11:24:29 +0200 Subject: [PATCH 16/18] refactor: remove console.log --- app/[lang]/(live)/(public)/login/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/[lang]/(live)/(public)/login/route.ts b/app/[lang]/(live)/(public)/login/route.ts index fa9db75aa..5cbc22d9b 100644 --- a/app/[lang]/(live)/(public)/login/route.ts +++ b/app/[lang]/(live)/(public)/login/route.ts @@ -95,7 +95,7 @@ export async function GET( ui_locales: context.params.lang, } ) - console.log(redirectUrl) + if (redirectUrl) { return NextResponse.redirect(redirectUrl, { headers: redirectHeaders, From ebd93db3d001d912560d1ff0d7faeb6ee4b9323b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Thu, 23 May 2024 14:14:28 +0200 Subject: [PATCH 17/18] fix: env variables in correct order --- .env.local.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.local.example b/.env.local.example index 721213c83..f24f3b573 100644 --- a/.env.local.example +++ b/.env.local.example @@ -19,7 +19,6 @@ NEXTAUTH_REDIRECT_PROXY_URL="http://localhost:3000/api/web/auth" NEXTAUTH_SECRET="" # NEXTAUTH_URL="DO NOT SET THIS HERE, it is managed in next.config.js" REVALIDATE_SECRET="" -WEBVIEW_ENCRYPTION_KEY="MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=" SEAMLESS_LOGIN_DA="http://www.example.dk/updatelogin" SEAMLESS_LOGIN_DE="http://www.example.de/updatelogin" SEAMLESS_LOGIN_EN="http://www.example.com/updatelogin" @@ -32,3 +31,4 @@ SEAMLESS_LOGOUT_EN="http://www.example.com/updatelogout?newweb" SEAMLESS_LOGOUT_FI="http://www.example.fi/updatelogout?newweb" SEAMLESS_LOGOUT_NO="http://www.example.no/updatelogout?newweb" SEAMLESS_LOGOUT_SV="http://www.example.sv/updatelogout?newweb" +WEBVIEW_ENCRYPTION_KEY="MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=" \ No newline at end of file From bb4b383cafbdf38e03ac062ce21511a2b9381c04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matilda=20Landstr=C3=B6m?= Date: Thu, 23 May 2024 14:15:02 +0200 Subject: [PATCH 18/18] fix: destructure lang prop --- components/MyPages/Sidebar/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/MyPages/Sidebar/index.tsx b/components/MyPages/Sidebar/index.tsx index 379786cad..ebb5047b5 100644 --- a/components/MyPages/Sidebar/index.tsx +++ b/components/MyPages/Sidebar/index.tsx @@ -11,7 +11,7 @@ import styles from "./sidebar.module.css" import { LangParams } from "@/types/params" -export default async function Sidebar(params: LangParams) { +export default async function Sidebar({ lang }: LangParams) { const navigation = await serverClient().contentstack.myPages.navigation.get() return ( @@ -44,7 +44,7 @@ export default async function Sidebar(params: LangParams) { ))} - + Log out