mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 12:03:17 +00:00
mfa selection, setup page
This commit is contained in:
@@ -1,35 +0,0 @@
|
||||
"use client";
|
||||
import { Button, ButtonVariants } from "#/ui/Button";
|
||||
import { TextInput } from "#/ui/Input";
|
||||
import UserAvatar from "#/ui/UserAvatar";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
export default function Page() {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center space-y-4">
|
||||
<h1>Password</h1>
|
||||
<p className="ztdl-p mb-6 block">Enter your password.</p>
|
||||
|
||||
<UserAvatar
|
||||
showDropdown
|
||||
displayName="Max Peintner"
|
||||
loginName="max@zitadel.com"
|
||||
></UserAvatar>
|
||||
|
||||
<div className="w-full">
|
||||
<TextInput type="password" label="Password" />
|
||||
</div>
|
||||
<div className="flex w-full flex-row items-center justify-between">
|
||||
<Button
|
||||
onClick={() => router.back()}
|
||||
variant={ButtonVariants.Secondary}
|
||||
>
|
||||
back
|
||||
</Button>
|
||||
<Button variant={ButtonVariants.Primary}>continue</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -9,8 +9,8 @@ export default function Page() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center space-y-4">
|
||||
<h1>Password</h1>
|
||||
<p className="ztdl-p mb-6 block">Enter your password.</p>
|
||||
<h1>Second Factor</h1>
|
||||
<p className="ztdl-p mb-6 block">Please select a second factor.</p>
|
||||
|
||||
<UserAvatar
|
||||
showDropdown
|
||||
|
||||
37
apps/login/app/(login)/totp/set/page.tsx
Normal file
37
apps/login/app/(login)/totp/set/page.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { getBrandingSettings, getLoginSettings, server } from "#/lib/zitadel";
|
||||
import DynamicTheme from "#/ui/DynamicTheme";
|
||||
import TOTPForm from "#/ui/TOTPForm";
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: Record<string | number | symbol, string | undefined>;
|
||||
}) {
|
||||
const { loginName, authRequestId, sessionId, organization, code, submit } =
|
||||
searchParams;
|
||||
|
||||
const branding = await getBrandingSettings(server, organization);
|
||||
const loginSettings = await getLoginSettings(server, organization);
|
||||
|
||||
return (
|
||||
<DynamicTheme branding={branding}>
|
||||
<div className="flex flex-col items-center space-y-4">
|
||||
<h1>Verify 2-Factor</h1>
|
||||
<p className="ztdl-p">Enter the code from your authenticator app. </p>
|
||||
|
||||
<div>
|
||||
{loginSettings?.secondFactors.map((factor) => {
|
||||
return (
|
||||
<div>
|
||||
{factor === 1 && <div>TOTP</div>}
|
||||
{factor === 2 && <div>U2F</div>}
|
||||
{factor === 3 && <div>OTP Email</div>}
|
||||
{factor === 4 && <div>OTP Sms</div>}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</DynamicTheme>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
import { server, deleteSession } from "#/lib/zitadel";
|
||||
import {
|
||||
server,
|
||||
deleteSession,
|
||||
getUserById,
|
||||
listHumanAuthFactors,
|
||||
} from "#/lib/zitadel";
|
||||
import {
|
||||
SessionCookie,
|
||||
getMostRecentSessionCookie,
|
||||
@@ -100,12 +105,23 @@ export async function PUT(request: NextRequest) {
|
||||
challenges,
|
||||
undefined,
|
||||
authRequestId
|
||||
).then((session) => {
|
||||
console.log(session);
|
||||
).then(async (session) => {
|
||||
// if password, check if user has MFA methods
|
||||
let authFactors;
|
||||
if (password && session.factors?.user?.id) {
|
||||
const response = await listHumanAuthFactors(
|
||||
server,
|
||||
session.factors?.user?.id
|
||||
);
|
||||
if (response.result && response.result.length) {
|
||||
authFactors = response.result;
|
||||
}
|
||||
}
|
||||
return NextResponse.json({
|
||||
sessionId: session.id,
|
||||
factors: session.factors,
|
||||
challenges: session.challenges,
|
||||
authFactors,
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import {
|
||||
LegalAndSupportSettings,
|
||||
PasswordComplexitySettings,
|
||||
ZitadelServer,
|
||||
ZitadelServerOptions,
|
||||
user,
|
||||
@@ -15,8 +17,6 @@ import {
|
||||
AddHumanUserResponse,
|
||||
BrandingSettings,
|
||||
ListSessionsResponse,
|
||||
LegalAndSupportSettings,
|
||||
PasswordComplexitySettings,
|
||||
GetSessionResponse,
|
||||
VerifyEmailResponse,
|
||||
Checks,
|
||||
@@ -40,6 +40,7 @@ import {
|
||||
CreateCallbackResponse,
|
||||
RequestChallenges,
|
||||
TextQueryMethod,
|
||||
ListHumanAuthFactorsResponse,
|
||||
AddHumanUserRequest,
|
||||
} from "@zitadel/server";
|
||||
|
||||
@@ -257,6 +258,14 @@ export async function addHumanUser(
|
||||
);
|
||||
}
|
||||
|
||||
export async function listHumanAuthFactors(
|
||||
server: ZitadelServer,
|
||||
userId: string
|
||||
): Promise<ListHumanAuthFactorsResponse> {
|
||||
const managementService = management.getManagement(server);
|
||||
return managementService.listHumanAuthFactors({ userId }, {});
|
||||
}
|
||||
|
||||
export async function listUsers(
|
||||
userName: string,
|
||||
organizationId: string
|
||||
|
||||
@@ -89,7 +89,7 @@ export default function PasswordForm({
|
||||
let continueWithMfa = undefined;
|
||||
if (
|
||||
loginSettings?.forceMfa &&
|
||||
loginSettings.secondFactors?.length >= 1 // TODO replace with user methods - if forceMFA is set and no user methods prompt to add method (/mfa/add)
|
||||
resp.authFactors?.length >= 1 // TODO if forceMFA is set and no user methods prompt to add method (/mfa/add)
|
||||
) {
|
||||
if (loginSettings.secondFactors?.length === 1) {
|
||||
continueWithMfa = loginSettings.secondFactors[0];
|
||||
@@ -97,6 +97,23 @@ export default function PasswordForm({
|
||||
// continueWithMfa = loginSettings.secondFactors[0];
|
||||
// render selection page for mfa (/mfa/select)
|
||||
}
|
||||
} else if (loginSettings?.forceMfa && resp.authFactors?.length === 0) {
|
||||
const params = new URLSearchParams(
|
||||
authRequestId
|
||||
? {
|
||||
loginName: resp.factors.user.loginName,
|
||||
authRequestId,
|
||||
}
|
||||
: {
|
||||
loginName: resp.factors.user.loginName,
|
||||
}
|
||||
);
|
||||
|
||||
if (organization) {
|
||||
params.append("organization", organization);
|
||||
}
|
||||
|
||||
return router.push(`/mfa/set?` + params);
|
||||
}
|
||||
// OIDC flows
|
||||
if (authRequestId && resp && resp.sessionId) {
|
||||
|
||||
Reference in New Issue
Block a user