From fb09285162454e5bd5fa45c69e0e1e9eff3e0bee Mon Sep 17 00:00:00 2001 From: peintnermax Date: Tue, 5 Mar 2024 11:31:05 +0100 Subject: [PATCH 01/29] rm forwarded header --- apps/login/middleware.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/login/middleware.ts b/apps/login/middleware.ts index 88badee8..303934a4 100644 --- a/apps/login/middleware.ts +++ b/apps/login/middleware.ts @@ -12,7 +12,7 @@ export function middleware(request: NextRequest) { const requestHeaders = new Headers(request.headers); requestHeaders.set("x-zitadel-login-client", SERVICE_USER_ID); - requestHeaders.set("Forwarded", `host="${request.nextUrl.host}"`); + // requestHeaders.set("Forwarded", `host="${request.nextUrl.host}"`); const responseHeaders = new Headers(); responseHeaders.set("Access-Control-Allow-Origin", "*"); From 38e5f5668c5d8eefce1b6df4541b53c182d638f5 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 10:34:08 +0100 Subject: [PATCH 02/29] add x-zitadel-forwarded --- apps/login/middleware.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/login/middleware.ts b/apps/login/middleware.ts index 303934a4..178df000 100644 --- a/apps/login/middleware.ts +++ b/apps/login/middleware.ts @@ -12,7 +12,7 @@ export function middleware(request: NextRequest) { const requestHeaders = new Headers(request.headers); requestHeaders.set("x-zitadel-login-client", SERVICE_USER_ID); - // requestHeaders.set("Forwarded", `host="${request.nextUrl.host}"`); + requestHeaders.set("x-zitadel-forwarded", `host="${request.nextUrl.host}"`); const responseHeaders = new Headers(); responseHeaders.set("Access-Control-Allow-Origin", "*"); From e7fc080338b5ea41c8bf194e52734dc9ca3ee617 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 10:42:44 +0100 Subject: [PATCH 03/29] headers --- apps/login/app/(login)/headers/page.tsx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 apps/login/app/(login)/headers/page.tsx diff --git a/apps/login/app/(login)/headers/page.tsx b/apps/login/app/(login)/headers/page.tsx new file mode 100644 index 00000000..d22a288b --- /dev/null +++ b/apps/login/app/(login)/headers/page.tsx @@ -0,0 +1,22 @@ +import { headers } from "next/headers"; + +export default function Page() { + const headersList = headers(); + const hds = [ + "x-zitadel-login-client", + "forwarded", + "x-zitadel-forwarded", + "host", + "referer", + ]; + return ( +
+

Headers

+ {hds.map((h) => ( +

+ {h}:{headersList.get(h)} +

+ ))} +
+ ); +} From e3664291ce2424b03ee089c51610078f3bf179b9 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 11:19:16 +0100 Subject: [PATCH 04/29] key --- apps/login/app/(login)/headers/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/login/app/(login)/headers/page.tsx b/apps/login/app/(login)/headers/page.tsx index d22a288b..a12ea774 100644 --- a/apps/login/app/(login)/headers/page.tsx +++ b/apps/login/app/(login)/headers/page.tsx @@ -13,7 +13,7 @@ export default function Page() {

Headers

{hds.map((h) => ( -

+

{h}:{headersList.get(h)}

))} From f809cd32a18322dd1e34fc2a7cdd348ccee48a5b Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 11:42:53 +0100 Subject: [PATCH 05/29] auto return lastsession if no hint --- apps/login/app/(login)/login/route.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index c229c738..2c98bfe4 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -30,9 +30,11 @@ function findSession( (s) => s.factors?.user?.loginName === authRequest.loginHint ); } + if (sessions.length) { + return sessions[0]; + } return undefined; } - export async function GET(request: NextRequest) { const searchParams = request.nextUrl.searchParams; const authRequestId = searchParams.get("authRequest"); From f6d8eff1a463e946ffe8df4977b0c06d6bab8fea Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 11:48:15 +0100 Subject: [PATCH 06/29] debug view --- apps/login/app/layout.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/login/app/layout.tsx b/apps/login/app/layout.tsx index edb42ec2..e5fbd198 100644 --- a/apps/login/app/layout.tsx +++ b/apps/login/app/layout.tsx @@ -23,7 +23,7 @@ export default async function RootLayout({ children: React.ReactNode; }) { // later only shown with dev mode enabled - const showNav = true; + const showNav = process.env.DEBUG === "true" ? true : false; const branding = await getBrandingSettings(server); let partial: Partial | undefined; @@ -47,8 +47,12 @@ export default async function RootLayout({
{showNav && } -
-
+
+
{showNav && (
From 503783fbf3c2592931438825a9156804e4177bb0 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 11:50:22 +0100 Subject: [PATCH 07/29] list env --- turbo.json | 1 + 1 file changed, 1 insertion(+) diff --git a/turbo.json b/turbo.json index 40e40266..3b73e9de 100644 --- a/turbo.json +++ b/turbo.json @@ -23,6 +23,7 @@ }, "globalDependencies": ["**/.env.*local"], "globalEnv": [ + "DEBUG", "ZITADEL_API_URL", "ZITADEL_SERVICE_USER_TOKEN", "ZITADEL_SYSTEM_API_URL", From 9e0d9d6c468d8e40a131a07a7caffa65509aef59 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 13:35:21 +0100 Subject: [PATCH 08/29] session, login prompt, select account to callback --- apps/login/app/(login)/login/route.ts | 20 +++++++++++++++++-- apps/login/ui/SessionItem.tsx | 28 ++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index 2c98bfe4..a3a760d8 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -38,10 +38,25 @@ function findSession( export async function GET(request: NextRequest) { const searchParams = request.nextUrl.searchParams; const authRequestId = searchParams.get("authRequest"); + const sessionId = searchParams.get("sessionId"); + const sessionCookies: SessionCookie[] = await getAllSessions(); + + if (authRequestId && sessionId) { + const cookie = sessionCookies.find((cookie) => cookie.id === sessionId); + + const session = { + sessionId: cookie?.id, + sessionToken: cookie?.token, + }; + const { callbackUrl } = await createCallback(server, { + authRequestId, + session, + }); + return NextResponse.redirect(callbackUrl); + } if (authRequestId) { const { authRequest } = await getAuthRequest(server, { authRequestId }); - const sessionCookies: SessionCookie[] = await getAllSessions(); const ids = sessionCookies.map((s) => s.id); let sessions: Session[] = []; @@ -57,7 +72,8 @@ export async function GET(request: NextRequest) { // if some accounts are available for selection and select_account is set if ( authRequest && - authRequest.prompt.includes(Prompt.PROMPT_SELECT_ACCOUNT) + (authRequest.prompt.includes(Prompt.PROMPT_SELECT_ACCOUNT) || + authRequest.prompt.includes(Prompt.PROMPT_LOGIN)) ) { const accountsUrl = new URL("/accounts", request.url); if (authRequest?.id) { diff --git a/apps/login/ui/SessionItem.tsx b/apps/login/ui/SessionItem.tsx index e181343d..1fa79f57 100644 --- a/apps/login/ui/SessionItem.tsx +++ b/apps/login/ui/SessionItem.tsx @@ -40,6 +40,32 @@ export default function SessionItem({ } } + // async function loginSession(authRequestId: string, sessionId: string) { + // setLoading(true); + // const res = await fetch( + // "/api/login?" + new URLSearchParams({ sessionId, authRequestId }), + // { + // method: "DELETE", + // headers: { + // "Content-Type": "application/json", + // }, + // body: JSON.stringify({ + // id: id, + // }), + // } + // ); + + // const response = await res.json(); + + // setLoading(false); + // if (!res.ok) { + // // setError(response.details); + // return Promise.reject(response); + // } else { + // return response; + // } + // } + const validPassword = session?.factors?.password?.verifiedAt; const validPasskey = session?.factors?.webAuthN?.verifiedAt; @@ -49,7 +75,7 @@ export default function SessionItem({ Date: Wed, 6 Mar 2024 13:44:15 +0100 Subject: [PATCH 09/29] handle account select --- apps/login/app/(login)/login/route.ts | 36 +++++++++++++-------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index a3a760d8..5b7220cb 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -45,15 +45,21 @@ export async function GET(request: NextRequest) { if (authRequestId && sessionId) { const cookie = sessionCookies.find((cookie) => cookie.id === sessionId); - const session = { - sessionId: cookie?.id, - sessionToken: cookie?.token, - }; - const { callbackUrl } = await createCallback(server, { - authRequestId, - session, - }); - return NextResponse.redirect(callbackUrl); + if (cookie && cookie.id && cookie.token) { + const session = { + sessionId: cookie?.id, + sessionToken: cookie?.token, + }; + const { callbackUrl } = await createCallback(server, { + authRequestId, + session, + }); + return NextResponse.redirect(callbackUrl); + } else { + const accountsUrl = new URL("/accounts", request.url); + accountsUrl.searchParams.set("authRequestId", authRequestId); + return NextResponse.redirect(accountsUrl); + } } if (authRequestId) { const { authRequest } = await getAuthRequest(server, { authRequestId }); @@ -85,10 +91,6 @@ export async function GET(request: NextRequest) { // check for loginHint, userId hint sessions let selectedSession = findSession(sessions, authRequest); - // if (!selectedSession) { - // selectedSession = sessions[0]; // TODO: remove - // } - if (selectedSession && selectedSession.id) { const cookie = sessionCookies.find( (cookie) => cookie.id === selectedSession?.id @@ -106,17 +108,13 @@ export async function GET(request: NextRequest) { return NextResponse.redirect(callbackUrl); } else { const accountsUrl = new URL("/accounts", request.url); - if (authRequest?.id) { - accountsUrl.searchParams.set("authRequestId", authRequest?.id); - } + accountsUrl.searchParams.set("authRequestId", authRequestId); return NextResponse.redirect(accountsUrl); } } else { const accountsUrl = new URL("/accounts", request.url); - if (authRequest?.id) { - accountsUrl.searchParams.set("authRequestId", authRequest?.id); - } + accountsUrl.searchParams.set("authRequestId", authRequestId); return NextResponse.redirect(accountsUrl); // return NextResponse.error(); From 73fde48e4389cf6d3871658ed0ff6f97b1a50ef9 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 13:54:44 +0100 Subject: [PATCH 10/29] submit sessionId --- apps/login/ui/SessionItem.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/login/ui/SessionItem.tsx b/apps/login/ui/SessionItem.tsx index 1fa79f57..47224630 100644 --- a/apps/login/ui/SessionItem.tsx +++ b/apps/login/ui/SessionItem.tsx @@ -79,7 +79,8 @@ export default function SessionItem({ new URLSearchParams( authRequestId ? { - loginName: session.factors?.user?.loginName as string, + // loginName: session.factors?.user?.loginName as string, + sessionId: session.id, authRequestId, } : { From 482990c2817d10b688faf223ace6c0a80354a868 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 14:13:38 +0100 Subject: [PATCH 11/29] login handler --- apps/login/app/(login)/login/route.ts | 65 +++++++++++++++++---------- apps/login/ui/SessionItem.tsx | 26 ----------- 2 files changed, 42 insertions(+), 49 deletions(-) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index 5b7220cb..e5ffc4ad 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -43,25 +43,42 @@ export async function GET(request: NextRequest) { const sessionCookies: SessionCookie[] = await getAllSessions(); if (authRequestId && sessionId) { - const cookie = sessionCookies.find((cookie) => cookie.id === sessionId); - - if (cookie && cookie.id && cookie.token) { - const session = { - sessionId: cookie?.id, - sessionToken: cookie?.token, - }; - const { callbackUrl } = await createCallback(server, { - authRequestId, - session, - }); - return NextResponse.redirect(callbackUrl); - } else { - const accountsUrl = new URL("/accounts", request.url); - accountsUrl.searchParams.set("authRequestId", authRequestId); - return NextResponse.redirect(accountsUrl); + console.log( + `Login with session: ${sessionId} and authRequest: ${authRequestId}` + ); + const ids = sessionCookies.map((s) => s.id); + + let sessions: Session[] = []; + if (ids && ids.length) { + sessions = await loadSessions(ids); + } + + let selectedSession = sessions.find((s) => s.id === sessionId); + + if (selectedSession && selectedSession.id) { + console.log(`Found session ${selectedSession.id}`); + const cookie = sessionCookies.find( + (cookie) => cookie.id === selectedSession?.id + ); + + if (cookie && cookie.id && cookie.token) { + console.log(`Found sessioncookie ${cookie.id}`); + + const session = { + sessionId: cookie?.id, + sessionToken: cookie?.token, + }; + + const { callbackUrl } = await createCallback(server, { + authRequestId, + session, + }); + return NextResponse.redirect(callbackUrl); + } } } if (authRequestId) { + console.log(`Login with authRequest: ${authRequestId}`); const { authRequest } = await getAuthRequest(server, { authRequestId }); const ids = sessionCookies.map((s) => s.id); @@ -122,17 +139,19 @@ export async function GET(request: NextRequest) { } } else { const loginNameUrl = new URL("/loginname", request.url); - if (authRequest?.id) { - loginNameUrl.searchParams.set("authRequestId", authRequest?.id); - if (authRequest.loginHint) { - loginNameUrl.searchParams.set("loginName", authRequest.loginHint); - loginNameUrl.searchParams.set("submit", "true"); // autosubmit - } + + loginNameUrl.searchParams.set("authRequestId", authRequestId); + if (authRequest?.loginHint) { + loginNameUrl.searchParams.set("loginName", authRequest.loginHint); + loginNameUrl.searchParams.set("submit", "true"); // autosubmit } return NextResponse.redirect(loginNameUrl); } } else { - return NextResponse.error(); + return NextResponse.json( + { error: "No authRequestId provided" }, + { status: 500 } + ); } } diff --git a/apps/login/ui/SessionItem.tsx b/apps/login/ui/SessionItem.tsx index 47224630..e3f81d94 100644 --- a/apps/login/ui/SessionItem.tsx +++ b/apps/login/ui/SessionItem.tsx @@ -40,32 +40,6 @@ export default function SessionItem({ } } - // async function loginSession(authRequestId: string, sessionId: string) { - // setLoading(true); - // const res = await fetch( - // "/api/login?" + new URLSearchParams({ sessionId, authRequestId }), - // { - // method: "DELETE", - // headers: { - // "Content-Type": "application/json", - // }, - // body: JSON.stringify({ - // id: id, - // }), - // } - // ); - - // const response = await res.json(); - - // setLoading(false); - // if (!res.ok) { - // // setError(response.details); - // return Promise.reject(response); - // } else { - // return response; - // } - // } - const validPassword = session?.factors?.password?.verifiedAt; const validPasskey = session?.factors?.webAuthN?.verifiedAt; From 5f980f0d8b062aa72faa20e3e88247d4d3083d26 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 14:17:13 +0100 Subject: [PATCH 12/29] authRequestId as param --- apps/login/app/(login)/login/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index e5ffc4ad..8a30919c 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -37,7 +37,7 @@ function findSession( } export async function GET(request: NextRequest) { const searchParams = request.nextUrl.searchParams; - const authRequestId = searchParams.get("authRequest"); + const authRequestId = searchParams.get("authRequestId"); const sessionId = searchParams.get("sessionId"); const sessionCookies: SessionCookie[] = await getAllSessions(); From a07bad548c2a49c187459adfcb8ee0be045da98e Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 14:18:48 +0100 Subject: [PATCH 13/29] authrequest searchparam --- apps/login/app/(login)/login/route.ts | 2 +- apps/login/ui/SessionItem.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index 8a30919c..e5ffc4ad 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -37,7 +37,7 @@ function findSession( } export async function GET(request: NextRequest) { const searchParams = request.nextUrl.searchParams; - const authRequestId = searchParams.get("authRequestId"); + const authRequestId = searchParams.get("authRequest"); const sessionId = searchParams.get("sessionId"); const sessionCookies: SessionCookie[] = await getAllSessions(); diff --git a/apps/login/ui/SessionItem.tsx b/apps/login/ui/SessionItem.tsx index e3f81d94..f8f34312 100644 --- a/apps/login/ui/SessionItem.tsx +++ b/apps/login/ui/SessionItem.tsx @@ -55,7 +55,7 @@ export default function SessionItem({ ? { // loginName: session.factors?.user?.loginName as string, sessionId: session.id, - authRequestId, + authRequest: authRequestId, } : { loginName: session.factors?.user?.loginName as string, From 7d579ec61df16334f4e1995957aa6f4dbb77216a Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 14:38:31 +0100 Subject: [PATCH 14/29] authRequest context from accounts page --- apps/login/app/(login)/accounts/page.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/login/app/(login)/accounts/page.tsx b/apps/login/app/(login)/accounts/page.tsx index 6c41d2f3..5761512d 100644 --- a/apps/login/app/(login)/accounts/page.tsx +++ b/apps/login/app/(login)/accounts/page.tsx @@ -36,7 +36,16 @@ export default async function Page({
- +
From 251f27594d3c87b8f0402a096c7c1f88e959315c Mon Sep 17 00:00:00 2001 From: peintnermax Date: Wed, 6 Mar 2024 14:44:48 +0100 Subject: [PATCH 15/29] request callback after pwd, passkey --- apps/login/ui/LoginPasskey.tsx | 36 ++++++++++++++++++++++------------ apps/login/ui/PasswordForm.tsx | 36 ++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/apps/login/ui/LoginPasskey.tsx b/apps/login/ui/LoginPasskey.tsx index e36b9bda..88b3f924 100644 --- a/apps/login/ui/LoginPasskey.tsx +++ b/apps/login/ui/LoginPasskey.tsx @@ -152,19 +152,29 @@ export default function LoginPasskey({ }, }; return submitLogin(data).then((resp) => { - return router.push( - `/signedin?` + - new URLSearchParams( - authRequestId - ? { - loginName: resp.factors.user.loginName, - authRequestId, - } - : { - loginName: resp.factors.user.loginName, - } - ) - ); + if (authRequestId && resp && resp.sessionId) { + return router.push( + `/login?` + + new URLSearchParams({ + sessionId: resp.sessionId, + authRequest: authRequestId, + }) + ); + } else { + return router.push( + `/signedin?` + + new URLSearchParams( + authRequestId + ? { + loginName: resp.factors.user.loginName, + authRequestId, + } + : { + loginName: resp.factors.user.loginName, + } + ) + ); + } }); } else { setLoading(false); diff --git a/apps/login/ui/PasswordForm.tsx b/apps/login/ui/PasswordForm.tsx index 52a1169d..e5fd0253 100644 --- a/apps/login/ui/PasswordForm.tsx +++ b/apps/login/ui/PasswordForm.tsx @@ -76,19 +76,29 @@ export default function PasswordForm({ }) ); } else { - return router.push( - `/signedin?` + - new URLSearchParams( - authRequestId - ? { - loginName: resp.factors.user.loginName, - authRequestId, - } - : { - loginName: resp.factors.user.loginName, - } - ) - ); + if (authRequestId && resp && resp.sessionId) { + return router.push( + `/login?` + + new URLSearchParams({ + sessionId: resp.sessionId, + authRequest: authRequestId, + }) + ); + } else { + return router.push( + `/signedin?` + + new URLSearchParams( + authRequestId + ? { + loginName: resp.factors.user.loginName, + authRequestId, + } + : { + loginName: resp.factors.user.loginName, + } + ) + ); + } } }); } From 324cd893a6bfc18aa1bb344d79b533c8bfb2c553 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Fri, 8 Mar 2024 11:39:17 +0100 Subject: [PATCH 16/29] security headers - csp --- apps/login/next.config.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/apps/login/next.config.js b/apps/login/next.config.js index f51127a9..f919c62b 100755 --- a/apps/login/next.config.js +++ b/apps/login/next.config.js @@ -1,4 +1,35 @@ /** @type {import('next').NextConfig} */ + +const secureHeaders = [ + { + key: "Strict-Transport-Security", + value: "max-age=63072000; includeSubDomains; preload", + }, + { + key: "Referrer-Policy", + value: "origin-when-cross-origin", + }, + { + key: "X-Frame-Options", + value: "SAMEORIGIN", + }, + { + key: "X-Content-Type-Options", + value: "nosniff", + }, + { + key: "X-XSS-Protection", + value: "1; mode=block", + }, + // img-src vercel.com needed for deploy button, + // script-src va.vercel-scripts.com for analytics/vercel scripts + { + key: "Content-Security-Policy", + value: + "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://va.vercel-scripts.com; connect-src 'self'; child-src; style-src 'self' 'unsafe-inline'; font-src 'self'; object-src 'none'; img-src 'self' https://vercel.com;", + }, +]; + const nextConfig = { reactStrictMode: true, // Recommended for the `pages` directory, default in `app`. swcMinify: true, @@ -21,6 +52,14 @@ const nextConfig = { }, ], }, + async headers() { + return [ + { + source: "/:path*", + headers: secureHeaders, + }, + ]; + }, }; module.exports = nextConfig; From 4fcbf77c15df54b27ef002779043377518df54d4 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Fri, 8 Mar 2024 11:53:21 +0100 Subject: [PATCH 17/29] create prompt --- apps/login/app/(login)/login/route.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index e5ffc4ad..31baa0af 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -80,6 +80,15 @@ export async function GET(request: NextRequest) { if (authRequestId) { console.log(`Login with authRequest: ${authRequestId}`); const { authRequest } = await getAuthRequest(server, { authRequestId }); + + if (authRequest && authRequest.prompt.includes(Prompt.PROMPT_CREATE)) { + const registerUrl = new URL("/register", request.url); + if (authRequest?.id) { + registerUrl.searchParams.set("authRequestId", authRequest?.id); + } + + return NextResponse.redirect(registerUrl); + } const ids = sessionCookies.map((s) => s.id); let sessions: Session[] = []; @@ -105,6 +114,7 @@ export async function GET(request: NextRequest) { return NextResponse.redirect(accountsUrl); } else { + // NONE prompt - silent authentication // check for loginHint, userId hint sessions let selectedSession = findSession(sessions, authRequest); From 08fae940dd905884a57459495c6e1f33e20900b0 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Fri, 8 Mar 2024 14:04:10 +0100 Subject: [PATCH 18/29] login prompt --- apps/login/app/(login)/login/route.ts | 69 ++++++++++++++++++--------- 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index 31baa0af..d9ba4e83 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -41,17 +41,16 @@ export async function GET(request: NextRequest) { const sessionId = searchParams.get("sessionId"); const sessionCookies: SessionCookie[] = await getAllSessions(); + const ids = sessionCookies.map((s) => s.id); + let sessions: Session[] = []; + if (ids && ids.length) { + sessions = await loadSessions(ids); + } if (authRequestId && sessionId) { console.log( `Login with session: ${sessionId} and authRequest: ${authRequestId}` ); - const ids = sessionCookies.map((s) => s.id); - - let sessions: Session[] = []; - if (ids && ids.length) { - sessions = await loadSessions(ids); - } let selectedSession = sessions.find((s) => s.id === sessionId); @@ -77,6 +76,7 @@ export async function GET(request: NextRequest) { } } } + if (authRequestId) { console.log(`Login with authRequest: ${authRequestId}`); const { authRequest } = await getAuthRequest(server, { authRequestId }); @@ -89,32 +89,58 @@ export async function GET(request: NextRequest) { return NextResponse.redirect(registerUrl); } - const ids = sessionCookies.map((s) => s.id); - - let sessions: Session[] = []; - if (ids && ids.length) { - sessions = await loadSessions(ids); - } else { - console.info("No session cookie found."); - sessions = []; - } // use existing session and hydrate it for oidc if (authRequest && sessions.length) { // if some accounts are available for selection and select_account is set - if ( - authRequest && - (authRequest.prompt.includes(Prompt.PROMPT_SELECT_ACCOUNT) || - authRequest.prompt.includes(Prompt.PROMPT_LOGIN)) - ) { + if (authRequest.prompt.includes(Prompt.PROMPT_SELECT_ACCOUNT)) { const accountsUrl = new URL("/accounts", request.url); if (authRequest?.id) { accountsUrl.searchParams.set("authRequestId", authRequest?.id); } return NextResponse.redirect(accountsUrl); - } else { + } else if (authRequest.prompt.includes(Prompt.PROMPT_LOGIN)) { + // if prompt is login + const loginNameUrl = new URL("/loginname", request.url); + if (authRequest?.id) { + loginNameUrl.searchParams.set("authRequestId", authRequest?.id); + } + + return NextResponse.redirect(loginNameUrl); + } else if (authRequest.prompt.includes(Prompt.PROMPT_NONE)) { // NONE prompt - silent authentication + + let selectedSession = findSession(sessions, authRequest); + + if (selectedSession && selectedSession.id) { + const cookie = sessionCookies.find( + (cookie) => cookie.id === selectedSession?.id + ); + + if (cookie && cookie.id && cookie.token) { + const session = { + sessionId: cookie?.id, + sessionToken: cookie?.token, + }; + const { callbackUrl } = await createCallback(server, { + authRequestId, + session, + }); + return NextResponse.redirect(callbackUrl); + } else { + return NextResponse.json( + { error: "No active session found" }, + { status: 500 } // TODO: check for correct status code + ); + } + } else { + return NextResponse.json( + { error: "No active session found" }, + { status: 500 } // TODO: check for correct status code + ); + } + } else { // check for loginHint, userId hint sessions let selectedSession = findSession(sessions, authRequest); @@ -144,7 +170,6 @@ export async function GET(request: NextRequest) { accountsUrl.searchParams.set("authRequestId", authRequestId); return NextResponse.redirect(accountsUrl); - // return NextResponse.error(); } } } else { From ff404c78c8229fa8039f9bd2acbfb81f52048d52 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Fri, 8 Mar 2024 14:13:11 +0100 Subject: [PATCH 19/29] hide nav --- apps/login/app/layout.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/apps/login/app/layout.tsx b/apps/login/app/layout.tsx index e5fbd198..04e5187c 100644 --- a/apps/login/app/layout.tsx +++ b/apps/login/app/layout.tsx @@ -9,6 +9,7 @@ import { getBrandingSettings } from "#/lib/zitadel"; import { server } from "../lib/zitadel"; import { BrandingSettings } from "@zitadel/server"; import ThemeProvider from "#/ui/ThemeProvider"; +import Theme from "#/ui/Theme"; const lato = Lato({ weight: ["400", "700", "900"], @@ -44,8 +45,20 @@ export default async function RootLayout({ -
- {showNav && } +
+ {showNav ? ( + + ) : ( +
+ +
+ )}
Date: Fri, 8 Mar 2024 14:41:56 +0100 Subject: [PATCH 20/29] login hint for login prompt --- apps/login/app/(login)/login/route.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index d9ba4e83..c02ddfe7 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -106,7 +106,9 @@ export async function GET(request: NextRequest) { if (authRequest?.id) { loginNameUrl.searchParams.set("authRequestId", authRequest?.id); } - + if (authRequest.loginHint) { + loginNameUrl.searchParams.set("loginName", authRequest.loginHint); + } return NextResponse.redirect(loginNameUrl); } else if (authRequest.prompt.includes(Prompt.PROMPT_NONE)) { // NONE prompt - silent authentication From 2ef1af862be22cb243c8de291265517aee40e241 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Mon, 11 Mar 2024 14:13:38 +0100 Subject: [PATCH 21/29] password for multiple authmethods --- apps/login/ui/UsernameForm.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/apps/login/ui/UsernameForm.tsx b/apps/login/ui/UsernameForm.tsx index c6d45be7..5fd098eb 100644 --- a/apps/login/ui/UsernameForm.tsx +++ b/apps/login/ui/UsernameForm.tsx @@ -68,7 +68,7 @@ export default function UsernameForm({ if (response.authMethodTypes.length == 1) { const method = response.authMethodTypes[0]; switch (method) { - case 1: //AuthenticationMethodType.AUTHENTICATION_METHOD_TYPE_PASSWORD: + case 1: // user has only password as auth method const paramsPassword: any = { loginName: values.loginName }; if (loginSettings?.passkeysType === 1) { @@ -127,6 +127,21 @@ export default function UsernameForm({ return router.push( "/passkey/login?" + new URLSearchParams(passkeyParams) ); + } else { + // user has no passkey setup and login settings allow passkeys + const paramsPasswordDefault: any = { loginName: values.loginName }; + + if (loginSettings?.passkeysType === 1) { + paramsPasswordDefault.promptPasswordless = `true`; // PasskeysType.PASSKEYS_TYPE_ALLOWED, + } + + if (authRequestId) { + paramsPasswordDefault.authRequestId = authRequestId; + } + + return router.push( + "/password?" + new URLSearchParams(paramsPasswordDefault) + ); } } }); From 49b86d2df17badf9a37b4996b2aeb84fee7ad096 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Mon, 11 Mar 2024 14:32:54 +0100 Subject: [PATCH 22/29] parse orgId from authrequest scope --- apps/login/app/(login)/login/route.ts | 14 ++++++++++++++ .../login/app/(login)/{layout.tsx => template.tsx} | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) rename apps/login/app/(login)/{layout.tsx => template.tsx} (95%) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index c02ddfe7..9cc4eca2 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -16,6 +16,8 @@ async function loadSessions(ids: string[]): Promise { return response?.sessions ?? []; } +const ORG_SCOPE_REGEX = /urn:zitadel:iam:org:id:([0-9]*)/g; + function findSession( sessions: Session[], authRequest: AuthRequest @@ -87,6 +89,18 @@ export async function GET(request: NextRequest) { registerUrl.searchParams.set("authRequestId", authRequest?.id); } + if ( + authRequest.scope && + authRequest.scope.find((s) => ORG_SCOPE_REGEX.test(s)) + ) { + const orgId = authRequest.scope + .find((s) => ORG_SCOPE_REGEX.test(s)) + ?.match(ORG_SCOPE_REGEX)?.[1]; + console.log(orgId); + if (orgId) { + registerUrl.searchParams.set("orgId", orgId); + } + } return NextResponse.redirect(registerUrl); } diff --git a/apps/login/app/(login)/layout.tsx b/apps/login/app/(login)/template.tsx similarity index 95% rename from apps/login/app/(login)/layout.tsx rename to apps/login/app/(login)/template.tsx index 381ffbd2..e938635f 100644 --- a/apps/login/app/(login)/layout.tsx +++ b/apps/login/app/(login)/template.tsx @@ -3,7 +3,7 @@ import React from "react"; import { getBrandingSettings, server } from "#/lib/zitadel"; import { Logo } from "#/ui/Logo"; -export default async function Layout({ +export default async function Template({ children, }: { children: React.ReactNode; From 7668113b964fc129f935bed4bc2309e093dfdc5c Mon Sep 17 00:00:00 2001 From: peintnermax Date: Mon, 11 Mar 2024 17:33:19 +0100 Subject: [PATCH 23/29] catch org context --- apps/login/app/(login)/headers/page.tsx | 22 --------- .../app/(login)/{template.tsx => layout.tsx} | 5 +- apps/login/app/(login)/login/route.ts | 48 +++++++++++++------ 3 files changed, 37 insertions(+), 38 deletions(-) delete mode 100644 apps/login/app/(login)/headers/page.tsx rename apps/login/app/(login)/{template.tsx => layout.tsx} (91%) diff --git a/apps/login/app/(login)/headers/page.tsx b/apps/login/app/(login)/headers/page.tsx deleted file mode 100644 index a12ea774..00000000 --- a/apps/login/app/(login)/headers/page.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { headers } from "next/headers"; - -export default function Page() { - const headersList = headers(); - const hds = [ - "x-zitadel-login-client", - "forwarded", - "x-zitadel-forwarded", - "host", - "referer", - ]; - return ( -
-

Headers

- {hds.map((h) => ( -

- {h}:{headersList.get(h)} -

- ))} -
- ); -} diff --git a/apps/login/app/(login)/template.tsx b/apps/login/app/(login)/layout.tsx similarity index 91% rename from apps/login/app/(login)/template.tsx rename to apps/login/app/(login)/layout.tsx index e938635f..851b7e75 100644 --- a/apps/login/app/(login)/template.tsx +++ b/apps/login/app/(login)/layout.tsx @@ -3,11 +3,14 @@ import React from "react"; import { getBrandingSettings, server } from "#/lib/zitadel"; import { Logo } from "#/ui/Logo"; -export default async function Template({ +export default async function Layout({ children, + params, }: { children: React.ReactNode; + params: any; }) { + console.log(params); const branding = await getBrandingSettings(server); let partial: Partial | undefined; if (branding) { diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index 9cc4eca2..2c6034f8 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -5,7 +5,7 @@ import { server, } from "#/lib/zitadel"; import { SessionCookie, getAllSessions } from "#/utils/cookies"; -import { Session, AuthRequest, Prompt } from "@zitadel/server"; +import { Session, AuthRequest, Prompt, login } from "@zitadel/server"; import { NextRequest, NextResponse } from "next/server"; async function loadSessions(ids: string[]): Promise { @@ -82,25 +82,29 @@ export async function GET(request: NextRequest) { if (authRequestId) { console.log(`Login with authRequest: ${authRequestId}`); const { authRequest } = await getAuthRequest(server, { authRequestId }); + let organization; + + if ( + authRequest?.scope && + authRequest.scope.find((s) => ORG_SCOPE_REGEX.test(s)) + ) { + const orgId = authRequest.scope.find((s) => ORG_SCOPE_REGEX.test(s)); + + if (orgId) { + const matched = orgId.replace("urn:zitadel:iam:org:id:", ""); + organization = matched; + } + } if (authRequest && authRequest.prompt.includes(Prompt.PROMPT_CREATE)) { const registerUrl = new URL("/register", request.url); if (authRequest?.id) { registerUrl.searchParams.set("authRequestId", authRequest?.id); } - - if ( - authRequest.scope && - authRequest.scope.find((s) => ORG_SCOPE_REGEX.test(s)) - ) { - const orgId = authRequest.scope - .find((s) => ORG_SCOPE_REGEX.test(s)) - ?.match(ORG_SCOPE_REGEX)?.[1]; - console.log(orgId); - if (orgId) { - registerUrl.searchParams.set("orgId", orgId); - } + if (organization) { + registerUrl.searchParams.set("organization", organization); } + return NextResponse.redirect(registerUrl); } @@ -112,6 +116,9 @@ export async function GET(request: NextRequest) { if (authRequest?.id) { accountsUrl.searchParams.set("authRequestId", authRequest?.id); } + if (organization) { + accountsUrl.searchParams.set("organization", organization); + } return NextResponse.redirect(accountsUrl); } else if (authRequest.prompt.includes(Prompt.PROMPT_LOGIN)) { @@ -123,6 +130,9 @@ export async function GET(request: NextRequest) { if (authRequest.loginHint) { loginNameUrl.searchParams.set("loginName", authRequest.loginHint); } + if (organization) { + loginNameUrl.searchParams.set("organization", organization); + } return NextResponse.redirect(loginNameUrl); } else if (authRequest.prompt.includes(Prompt.PROMPT_NONE)) { // NONE prompt - silent authentication @@ -178,13 +188,17 @@ export async function GET(request: NextRequest) { } else { const accountsUrl = new URL("/accounts", request.url); accountsUrl.searchParams.set("authRequestId", authRequestId); - + if (organization) { + accountsUrl.searchParams.set("organization", organization); + } return NextResponse.redirect(accountsUrl); } } else { const accountsUrl = new URL("/accounts", request.url); accountsUrl.searchParams.set("authRequestId", authRequestId); - + if (organization) { + accountsUrl.searchParams.set("organization", organization); + } return NextResponse.redirect(accountsUrl); } } @@ -197,6 +211,10 @@ export async function GET(request: NextRequest) { loginNameUrl.searchParams.set("submit", "true"); // autosubmit } + if (organization) { + loginNameUrl.searchParams.set("organization", organization); + } + return NextResponse.redirect(loginNameUrl); } } else { From 86e70acbcc0888dae5bd352122f79bb1bbfb65f5 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Tue, 12 Mar 2024 11:35:19 +0100 Subject: [PATCH 24/29] org filter --- apps/login/app/(login)/loginname/page.tsx | 4 +++- apps/login/app/api/loginname/route.ts | 10 ++++++--- apps/login/lib/zitadel.ts | 27 +++++++++++++++++++++-- apps/login/ui/UsernameForm.tsx | 25 +++++++++++++++------ packages/zitadel-server/src/index.ts | 3 +++ 5 files changed, 56 insertions(+), 13 deletions(-) diff --git a/apps/login/app/(login)/loginname/page.tsx b/apps/login/app/(login)/loginname/page.tsx index ecf4ac6d..98ae5535 100644 --- a/apps/login/app/(login)/loginname/page.tsx +++ b/apps/login/app/(login)/loginname/page.tsx @@ -8,9 +8,10 @@ export default async function Page({ }) { const loginName = searchParams?.loginName; const authRequestId = searchParams?.authRequestId; + const organization = searchParams?.organization; const submit: boolean = searchParams?.submit === "true"; - const loginSettings = await getLoginSettings(server); + const loginSettings = await getLoginSettings(server, organization); return (
@@ -21,6 +22,7 @@ export default async function Page({ loginSettings={loginSettings} loginName={loginName} authRequestId={authRequestId} + organization={organization} submit={submit} />
diff --git a/apps/login/app/api/loginname/route.ts b/apps/login/app/api/loginname/route.ts index 257e56e5..cd1823db 100644 --- a/apps/login/app/api/loginname/route.ts +++ b/apps/login/app/api/loginname/route.ts @@ -1,12 +1,15 @@ -import { listAuthenticationMethodTypes } from "#/lib/zitadel"; +import { listAuthenticationMethodTypes, listUsers } from "#/lib/zitadel"; import { createSessionAndUpdateCookie } from "#/utils/session"; import { NextRequest, NextResponse } from "next/server"; export async function POST(request: NextRequest) { const body = await request.json(); if (body) { - const { loginName, authRequestId } = body; - + const { loginName, authRequestId, organization } = body; + // TODO - search for users with org + // return listUsers(loginName).then((users) => { + // if (users.details && users.details.totalResult == 1) { + // } return createSessionAndUpdateCookie( loginName, undefined, @@ -33,6 +36,7 @@ export async function POST(request: NextRequest) { .catch((error) => { return NextResponse.json(error, { status: 500 }); }); + // }); } else { return NextResponse.error(); } diff --git a/apps/login/lib/zitadel.ts b/apps/login/lib/zitadel.ts index 9148fb9e..e075a43a 100644 --- a/apps/login/lib/zitadel.ts +++ b/apps/login/lib/zitadel.ts @@ -21,6 +21,8 @@ import { VerifyEmailResponse, SetSessionResponse, SetSessionRequest, + ListUsersResponse, + ListUsersRequest, DeleteSessionResponse, VerifyPasskeyRegistrationResponse, LoginSettings, @@ -35,6 +37,7 @@ import { CreateCallbackRequest, CreateCallbackResponse, RequestChallenges, + TextQueryMethod, AddHumanUserRequest, } from "@zitadel/server"; @@ -61,11 +64,12 @@ export async function getBrandingSettings( } export async function getLoginSettings( - server: ZitadelServer + server: ZitadelServer, + orgId?: string ): Promise { const settingsService = settings.getSettings(server); return settingsService - .getLoginSettings({}, {}) + .getLoginSettings({ ctx: orgId ? { orgId } : { instance: true } }, {}) .then((resp: GetLoginSettingsResponse) => resp.settings); } @@ -211,6 +215,25 @@ export async function addHumanUser( }); } +export async function listUsers(userName: string): Promise { + // TODO limit for organization + const userService = user.getUser(server); + + return userService.listUsers( + { + queries: [ + { + userNameQuery: { + userName, + method: TextQueryMethod.TEXT_QUERY_METHOD_EQUALS, + }, + }, + ], + }, + {} + ); +} + export async function startIdentityProviderFlow( server: ZitadelServer, { idpId, urls }: StartIdentityProviderIntentRequest diff --git a/apps/login/ui/UsernameForm.tsx b/apps/login/ui/UsernameForm.tsx index 5fd098eb..f555ae5a 100644 --- a/apps/login/ui/UsernameForm.tsx +++ b/apps/login/ui/UsernameForm.tsx @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { Button, ButtonVariants } from "./Button"; import { TextInput } from "./Input"; -import { useForm } from "react-hook-form"; +import { SubmitHandler, useForm } from "react-hook-form"; import { useRouter } from "next/navigation"; import { Spinner } from "./Spinner"; import { LoginSettings } from "@zitadel/server"; @@ -17,6 +17,7 @@ type Props = { loginSettings: LoginSettings | undefined; loginName: string | undefined; authRequestId: string | undefined; + organization?: string; submit: boolean; }; @@ -24,6 +25,7 @@ export default function UsernameForm({ loginSettings, loginName, authRequestId, + organization, submit, }: Props) { const { register, handleSubmit, formState } = useForm({ @@ -38,13 +40,17 @@ export default function UsernameForm({ const [loading, setLoading] = useState(false); const [error, setError] = useState(""); - async function submitLoginName(values: Inputs) { + async function submitLoginName(values: Inputs, organization?: string) { setLoading(true); - const body = { + let body: any = { loginName: values.loginName, }; + if (organization) { + body.organization = organization; + } + const res = await fetch("/api/loginname", { method: "POST", headers: { @@ -63,8 +69,11 @@ export default function UsernameForm({ return res.json(); } - async function setLoginNameAndGetAuthMethods(values: Inputs) { - return submitLoginName(values).then((response) => { + function setLoginNameAndGetAuthMethods( + values: Inputs, + organization?: string + ) { + return submitLoginName(values, organization).then((response) => { if (response.authMethodTypes.length == 1) { const method = response.authMethodTypes[0]; switch (method) { @@ -152,7 +161,7 @@ export default function UsernameForm({ useEffect(() => { if (submit && loginName) { // When we navigate to this page, we always want to be redirected if submit is true and the parameters are valid. - setLoginNameAndGetAuthMethods({ loginName }); + setLoginNameAndGetAuthMethods({ loginName }, organization); } }, []); @@ -180,7 +189,9 @@ export default function UsernameForm({ className="self-end" variant={ButtonVariants.Primary} disabled={loading || !formState.isValid} - onClick={handleSubmit(setLoginNameAndGetAuthMethods)} + onClick={handleSubmit((e) => + setLoginNameAndGetAuthMethods(e, organization) + )} > {loading && } continue diff --git a/packages/zitadel-server/src/index.ts b/packages/zitadel-server/src/index.ts index 1b6bfb5a..2c8f16a5 100644 --- a/packages/zitadel-server/src/index.ts +++ b/packages/zitadel-server/src/index.ts @@ -63,6 +63,7 @@ export { GetActiveIdentityProvidersResponse, GetActiveIdentityProvidersRequest, } from "./proto/server/zitadel/settings/v2beta/settings_service"; +export { TextQueryMethod } from "./proto/server/zitadel/object/v2beta/object"; export { AddHumanUserResponse, AddHumanUserRequest, @@ -80,6 +81,8 @@ export { StartIdentityProviderIntentResponse, RetrieveIdentityProviderIntentRequest, RetrieveIdentityProviderIntentResponse, + ListUsersRequest, + ListUsersResponse, } from "./proto/server/zitadel/user/v2beta/user_service"; export { SetHumanPasswordResponse, From aa7a4043933df0bd8a95af121cbaca5202d99e64 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Thu, 14 Mar 2024 14:42:05 +0100 Subject: [PATCH 25/29] Update apps/login/app/(login)/layout.tsx Co-authored-by: Elio Bischof --- apps/login/app/(login)/layout.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/login/app/(login)/layout.tsx b/apps/login/app/(login)/layout.tsx index 851b7e75..d3d690e5 100644 --- a/apps/login/app/(login)/layout.tsx +++ b/apps/login/app/(login)/layout.tsx @@ -10,7 +10,6 @@ export default async function Layout({ children: React.ReactNode; params: any; }) { - console.log(params); const branding = await getBrandingSettings(server); let partial: Partial | undefined; if (branding) { From 5f5f6f3699c338f487457e4859893e8dcdef24cd Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Thu, 14 Mar 2024 14:43:45 +0100 Subject: [PATCH 26/29] Update apps/login/app/(login)/login/route.ts Co-authored-by: Elio Bischof --- apps/login/app/(login)/login/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index 2c6034f8..edb90c86 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -16,7 +16,7 @@ async function loadSessions(ids: string[]): Promise { return response?.sessions ?? []; } -const ORG_SCOPE_REGEX = /urn:zitadel:iam:org:id:([0-9]*)/g; +const ORG_SCOPE_REGEX = /urn:zitadel:iam:org:id:([0-9]+)/g; function findSession( sessions: Session[], From 0e9928d5e11c95e21f79a4bb2ec21bf9df8699a9 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Thu, 14 Mar 2024 14:45:42 +0100 Subject: [PATCH 27/29] Update apps/login/app/layout.tsx Co-authored-by: Elio Bischof --- apps/login/app/layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/login/app/layout.tsx b/apps/login/app/layout.tsx index 04e5187c..f3395c19 100644 --- a/apps/login/app/layout.tsx +++ b/apps/login/app/layout.tsx @@ -24,7 +24,7 @@ export default async function RootLayout({ children: React.ReactNode; }) { // later only shown with dev mode enabled - const showNav = process.env.DEBUG === "true" ? true : false; + const showNav = process.env.DEBUG === "true"; const branding = await getBrandingSettings(server); let partial: Partial | undefined; From d653763ff1fbb73e00f4f8bda2f004047e0795bf Mon Sep 17 00:00:00 2001 From: peintnermax Date: Thu, 14 Mar 2024 16:27:12 +0100 Subject: [PATCH 28/29] get group from string --- apps/login/app/(login)/login/route.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index edb90c86..a96b2a16 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -16,7 +16,7 @@ async function loadSessions(ids: string[]): Promise { return response?.sessions ?? []; } -const ORG_SCOPE_REGEX = /urn:zitadel:iam:org:id:([0-9]+)/g; +const ORG_SCOPE_REGEX = /urn:zitadel:iam:org:id:([0-9]+)/; function findSession( sessions: Session[], @@ -91,8 +91,8 @@ export async function GET(request: NextRequest) { const orgId = authRequest.scope.find((s) => ORG_SCOPE_REGEX.test(s)); if (orgId) { - const matched = orgId.replace("urn:zitadel:iam:org:id:", ""); - organization = matched; + const matched = ORG_SCOPE_REGEX.exec(orgId); + organization = matched?.[1] ?? ""; } } From 952a1c85bef6685ea914cb4157e656e1b34e3ef8 Mon Sep 17 00:00:00 2001 From: peintnermax Date: Thu, 14 Mar 2024 16:30:07 +0100 Subject: [PATCH 29/29] doc, 400 --- apps/login/app/(login)/login/route.ts | 4 ++-- apps/login/middleware.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/(login)/login/route.ts index a96b2a16..7751651f 100644 --- a/apps/login/app/(login)/login/route.ts +++ b/apps/login/app/(login)/login/route.ts @@ -157,13 +157,13 @@ export async function GET(request: NextRequest) { } else { return NextResponse.json( { error: "No active session found" }, - { status: 500 } // TODO: check for correct status code + { status: 400 } // TODO: check for correct status code ); } } else { return NextResponse.json( { error: "No active session found" }, - { status: 500 } // TODO: check for correct status code + { status: 400 } // TODO: check for correct status code ); } } else { diff --git a/apps/login/middleware.ts b/apps/login/middleware.ts index 178df000..504d0fd5 100644 --- a/apps/login/middleware.ts +++ b/apps/login/middleware.ts @@ -12,6 +12,7 @@ export function middleware(request: NextRequest) { const requestHeaders = new Headers(request.headers); requestHeaders.set("x-zitadel-login-client", SERVICE_USER_ID); + // this is a workaround for the next.js server not forwarding the host header requestHeaders.set("x-zitadel-forwarded", `host="${request.nextUrl.host}"`); const responseHeaders = new Headers();