finish flow

This commit is contained in:
Max Peintner
2024-11-18 17:30:46 +01:00
parent fd90fcb752
commit 56f2b90c76
8 changed files with 72 additions and 24 deletions

View File

@@ -151,7 +151,8 @@
},
"signedin": {
"title": "Willkommen {user}!",
"description": "Sie sind angemeldet."
"description": "Sie sind angemeldet.",
"continue": "Weiter"
},
"verify": {
"userIdMissing": "Keine Benutzer-ID angegeben!",

View File

@@ -151,7 +151,8 @@
},
"signedin": {
"title": "Welcome {user}!",
"description": "You are signed in."
"description": "You are signed in.",
"continue": "Continue"
},
"verify": {
"userIdMissing": "No userId provided!",

View File

@@ -151,7 +151,8 @@
},
"signedin": {
"title": "¡Bienvenido {user}!",
"description": "Has iniciado sesión."
"description": "Has iniciado sesión.",
"continue": "Continuar"
},
"verify": {
"userIdMissing": "¡No se proporcionó userId!",

View File

@@ -151,7 +151,8 @@
},
"signedin": {
"title": "Benvenuto {user}!",
"description": "Sei connesso."
"description": "Sei connesso.",
"continue": "Continua"
},
"verify": {
"userIdMissing": "Nessun userId fornito!",

View File

@@ -386,3 +386,11 @@ In future, self service options to jump to are shown below, like:
- logout
> NOTE: This page has to be explicitly enabled or act as a fallback if no default redirect is set.
## Currently NOT Supported
- loginSettings.disableLoginWithEmail
- loginSettings.disableLoginWithPhone
- loginSettings.allowExternalIdp - this will be deprecated with the new login as it can be determined by the available IDPs
- loginSettings.forceMfaLocalOnly
- loginSettings lifetimes - all besides Multifactor Init Check can be implemented. for the Init Check, an external storage or a timestamp has to be implemented which keeps track of the last verification

View File

@@ -1,14 +1,21 @@
import { Button, ButtonVariants } from "@/components/button";
import { DynamicTheme } from "@/components/dynamic-theme";
import { SelfServiceMenu } from "@/components/self-service-menu";
import { UserAvatar } from "@/components/user-avatar";
import { getMostRecentCookieWithLoginname } from "@/lib/cookies";
import { createCallback, getBrandingSettings, getSession } from "@/lib/zitadel";
import {
createCallback,
getBrandingSettings,
getLoginSettings,
getSession,
} from "@/lib/zitadel";
import { create } from "@zitadel/client";
import {
CreateCallbackRequestSchema,
SessionSchema,
} from "@zitadel/proto/zitadel/oidc/v2/oidc_service_pb";
import { getLocale, getTranslations } from "next-intl/server";
import Link from "next/link";
import { redirect } from "next/navigation";
async function loadSession(loginName: string, authRequestId?: string) {
@@ -48,6 +55,11 @@ export default async function Page({ searchParams }: { searchParams: any }) {
const branding = await getBrandingSettings(organization);
let loginSettings;
if (!authRequestId) {
loginSettings = await getLoginSettings(organization);
}
return (
<DynamicTheme branding={branding}>
<div className="flex flex-col items-center space-y-4">
@@ -66,6 +78,22 @@ export default async function Page({ searchParams }: { searchParams: any }) {
{sessionFactors?.id && (
<SelfServiceMenu sessionId={sessionFactors?.id} />
)}
{loginSettings?.defaultRedirectUri && (
<div className="mt-8 flex w-full flex-row items-center">
<span className="flex-grow"></span>
<Link href={loginSettings?.defaultRedirectUri}>
<Button
type="submit"
className="self-end"
variant={ButtonVariants.Primary}
>
{t("continue")}
</Button>
</Link>
</div>
)}
</div>
</DynamicTheme>
);

View File

@@ -176,15 +176,15 @@ export function LoginPasskey({
},
};
return submitLogin(data).then((resp) => {
return submitLogin(data).then(async (resp) => {
return authRequestId && resp?.sessionId
? finishFlow({
? await finishFlow({
sessionId: resp.sessionId,
authRequestId: authRequestId,
organization: organization,
})
: resp?.factors?.user?.loginName
? finishFlow({
? await finishFlow({
loginName: resp.factors.user.loginName,
organization: organization,
})

View File

@@ -1,4 +1,5 @@
import { redirect } from "next/navigation";
import { getLoginSettings } from "./zitadel";
type FinishFlowCommand =
| {
@@ -8,25 +9,32 @@ type FinishFlowCommand =
| { loginName: string };
/**
* on client: redirects user back to OIDC application or to a success page
* for client: redirects user back to OIDC application or to a success page when using authRequestId, check if a default redirect and redirect to it, or just redirect to a success page with the loginName
* @param command
* @returns
*/
export function finishFlow(
export async function finishFlow(
command: FinishFlowCommand & { organization?: string },
) {
return "sessionId" in command && "authRequestId" in command
? redirect(
`/login?` +
new URLSearchParams({
sessionId: command.sessionId,
authRequest: command.authRequestId,
}),
)
: redirect(
`/signedin?` +
new URLSearchParams({
loginName: command.loginName,
}),
);
if ("sessionId" in command && "authRequestId" in command) {
return redirect(
`/login?` +
new URLSearchParams({
sessionId: command.sessionId,
authRequest: command.authRequestId,
}),
);
}
const loginSettings = await getLoginSettings(command.organization);
if (loginSettings?.defaultRedirectUri) {
return redirect(loginSettings.defaultRedirectUri);
}
return redirect(
`/signedin?` +
new URLSearchParams({
loginName: command.loginName,
}),
);
}