From 8ab77a5522ff56b2e6e1e19609ce9dc7bee5402a Mon Sep 17 00:00:00 2001 From: Hrishikesh Vaipurkar Date: Wed, 17 Jul 2024 16:12:18 +0200 Subject: [PATCH] feat: SW-162 Updated as per review comments --- .../(live)/(protected)/mfa-login/route.ts | 7 +- auth.ts | 70 ++++++++++++------- middlewares/authRequired.ts | 12 ++-- next.config.js | 7 +- types/auth.d.ts | 1 - 5 files changed, 59 insertions(+), 38 deletions(-) diff --git a/app/[lang]/(live)/(protected)/mfa-login/route.ts b/app/[lang]/(live)/(protected)/mfa-login/route.ts index 297c169a0..bec0a3eb5 100644 --- a/app/[lang]/(live)/(protected)/mfa-login/route.ts +++ b/app/[lang]/(live)/(protected)/mfa-login/route.ts @@ -41,18 +41,13 @@ export async function GET( * https://github.com/nextauthjs/next-auth/blob/3c035ec/packages/next-auth/src/lib/actions.ts#L76 */ const redirectUrl = await signIn( - "curity", + "curity-mfa", { redirectTo, redirect: false, }, { ui_locales: context.params.lang, - scope: "profile_update openid profile", - // The below acr value is required as for New Web same Curity Client is used for MFA - // while in current web it is being setup using different Curity Client ID and secret - acr_values: - "urn:se:curity:authentication:otp-authenticator:OTP-Authenticator_web", } ) diff --git a/auth.ts b/auth.ts index a5393514b..565be480c 100644 --- a/auth.ts +++ b/auth.ts @@ -1,4 +1,4 @@ -import { decode,encode } from "@auth/core/jwt" +import { encode } from "@auth/core/jwt" import { cookies } from "next/headers" import NextAuth from "next-auth" @@ -22,18 +22,39 @@ function getLoginType(user: User) { } } -const customProvider = { +const sharedConfig = { clientId: env.CURITY_CLIENT_ID_USER, clientSecret: env.CURITY_CLIENT_SECRET_USER, - id: "curity", - name: "Curity", - type: "oidc", // FIXME: This is incorrect. We should not hard code this. // It should be ${env.CURITY_ISSUER_USER}. // This change requires sync between Curity deploy and CurrentWeb and NewWeb. issuer: "https://scandichotels.com", authorization: { url: `${env.CURITY_ISSUER_USER}/oauth/v2/authorize`, + }, + token: { + url: `${env.CURITY_ISSUER_USER}/oauth/v2/token`, + }, + userinfo: { + url: `${env.CURITY_ISSUER_USER}/oauth/v2/userinfo`, + }, + profile(profile: User) { + return { + id: profile.id, + sub: profile.sub, + given_name: profile.given_name, + login_with: profile.login_with, + } + }, +} + +const curityProvider = { + ...sharedConfig, + id: "curity", + name: "Curity", + type: "oidc", + authorization: { + ...sharedConfig.authorization, params: { scope: ["openid", "profile"].join(" "), /** @@ -44,27 +65,30 @@ const customProvider = { acr_values: "acr", }, }, - token: { - url: `${env.CURITY_ISSUER_USER}/oauth/v2/token`, - }, - userinfo: { - url: `${env.CURITY_ISSUER_USER}/oauth/v2/userinfo`, - }, +} satisfies OIDCConfig - profile(profile) { - return { - id: profile.id, - sub: profile.sub, - given_name: profile.given_name, - login_with: profile.login_with, - acr: profile.acr, - } +const curityMFAProvider = { + ...sharedConfig, + id: "curity-mfa", + name: "Curity MFA", + type: "oidc", + authorization: { + ...sharedConfig.authorization, + params: { + scope: ["profile_update", "openid"].join(" "), + /** + * The below acr value is required as for New Web same Curity Client is used for MFA + * while in current web it is being setup using different Curity Client ID and secret + */ + acr_values: + "urn:se:curity:authentication:otp-authenticator:OTP-Authenticator_web", + }, }, } satisfies OIDCConfig export const config = { debug: env.NEXTAUTH_DEBUG, - providers: [customProvider], + providers: [curityProvider, curityMFAProvider], redirectProxyUrl: env.NEXTAUTH_REDIRECT_PROXY_URL, trustHost: true, session: { @@ -117,10 +141,7 @@ export const config = { return true }, async jwt({ account, session, token, trigger, user }) { - if ( - user?.acr == - "urn:se:curity:authentication:otp-authenticator:OTP-Authenticator_web" - ) { + if (account?.provider == "curity-mfa") { const cookieStore = cookies() const value = token.access_token const secret = env.NEXTAUTH_SECRET @@ -135,6 +156,7 @@ export const config = { cookieStore.set("_SecureMFA-token", mfaCookie.toString(), { maxAge: maxAge, }) + return null } const loginType = getLoginType(user) diff --git a/middlewares/authRequired.ts b/middlewares/authRequired.ts index a258cc422..56f80708b 100644 --- a/middlewares/authRequired.ts +++ b/middlewares/authRequired.ts @@ -55,7 +55,7 @@ export const middleware = auth(async (request) => { nextUrlClone.host = publicUrl.host nextUrlClone.hostname = publicUrl.hostname - const isMFAValid = async function () { + async function isMFAInvalid() { const cookieStore = cookies() const mfaCookieValue = cookieStore.get("_SecureMFA-token")?.value if (mfaCookieValue) { @@ -66,22 +66,22 @@ export const middleware = auth(async (request) => { salt: "_SecureMFA-token", }) if (mfaToken?.exp) { - return true + return false } } catch (e) { console.log("JWT decode failed", e) cookieStore.set("_SecureMFA-token", "", { maxAge: 0 }) - return false + return true } } else { - return false + return true } } if (isLoggedIn && !hasError) { const isMFAPath = mfaRequired.includes(nextUrl.pathname) - const mfaValid = isMFAPath ? await isMFAValid() : true - if (!mfaValid) { + const mfaInvalid = isMFAPath ? await isMFAInvalid() : false + if (mfaInvalid) { const mfaLoginUrl = mfaLogin[lang] const nextUrlClone = nextUrl.clone() nextUrlClone.host = publicUrl.host diff --git a/next.config.js b/next.config.js index 60e5a38d9..e5011a6c3 100644 --- a/next.config.js +++ b/next.config.js @@ -1,7 +1,7 @@ import createJiti from "jiti" import { fileURLToPath } from "url" -import { login, logout } from "./constants/routes/handleAuth.js" +import { login, logout, mfaLogin } from "./constants/routes/handleAuth.js" import { hotelReservation } from "./constants/routes/hotelReservation.js" import { myPages } from "./constants/routes/myPages.js" @@ -80,6 +80,11 @@ const nextConfig = { { source: logout.fi, destination: "/fi/logout" }, { source: logout.no, destination: "/no/logout" }, { source: logout.sv, destination: "/sv/logout" }, + { source: mfaLogin.da, destination: "/da/mfa-login" }, + { source: mfaLogin.de, destination: "/de/mfa-login" }, + { source: mfaLogin.fi, destination: "/fi/mfa-login" }, + { source: mfaLogin.no, destination: "/no/mfa-login" }, + { source: mfaLogin.sv, destination: "/sv/mfa-login" }, { source: `${myPages.en}/:path*`, destination: `/en/my-pages/:path*`, diff --git a/types/auth.d.ts b/types/auth.d.ts index 7755e7800..e3ac612d2 100644 --- a/types/auth.d.ts +++ b/types/auth.d.ts @@ -27,6 +27,5 @@ declare module "next-auth" { sub: string email?: string login_with: string - acr?: string } }