mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 18:02:33 +00:00
mfa, otp i18n
This commit is contained in:
@@ -59,6 +59,25 @@
|
||||
"description": "Choose one of the following second factors."
|
||||
}
|
||||
},
|
||||
"otp": {
|
||||
"verify": {
|
||||
"title": "Verify 2-Factor",
|
||||
"totpDescription": "Enter the code from your authenticator app.",
|
||||
"smsDescription": "Enter the code you received via SMS.",
|
||||
"emailDescription": "Enter the code you received via email.",
|
||||
"noCodeReceived": "Didn't receive a code?",
|
||||
"resendCode": "Resend code",
|
||||
"submit": "Continue"
|
||||
},
|
||||
"set": {
|
||||
"title": "Set up 2-Factor",
|
||||
"totpDescription": "Scan the QR code with your authenticator app.",
|
||||
"smsDescription": "Enter your phone number to receive a code via SMS.",
|
||||
"emailDescription": "Enter your email address to receive a code via email.",
|
||||
"totpRegisterDescription": "Scan the QR Code or navigate to the URL manually.",
|
||||
"submit": "Continue"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"unknownContext": "Could not get the context of the user. Make sure to enter the username first or provide a loginName as searchParam.",
|
||||
"sessionExpired": "You need to have a valid session in order to continue."
|
||||
|
||||
@@ -85,7 +85,7 @@ export default async function Page({
|
||||
)}
|
||||
|
||||
{!(loginName || sessionId) && (
|
||||
<Alert>{t("error.unknownContext")}</Alert>
|
||||
<Alert>{t("error:unknownContext")}</Alert>
|
||||
)}
|
||||
|
||||
{sessionFactors ? (
|
||||
|
||||
@@ -122,7 +122,7 @@ export default async function Page({
|
||||
)}
|
||||
|
||||
{!(loginName || sessionId) && (
|
||||
<Alert>{t("error.unknownContext")}</Alert>
|
||||
<Alert>{t("error:unknownContext")}</Alert>
|
||||
)}
|
||||
|
||||
{!valid && <Alert>{t("error.sessionExpired")}</Alert>}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { LoginOTP } from "@/components/login-otp";
|
||||
import { UserAvatar } from "@/components/user-avatar";
|
||||
import { loadMostRecentSession } from "@/lib/session";
|
||||
import { getBrandingSettings } from "@/lib/zitadel";
|
||||
import { getLocale, getTranslations } from "next-intl/server";
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
@@ -12,6 +13,9 @@ export default async function Page({
|
||||
searchParams: Record<string | number | symbol, string | undefined>;
|
||||
params: Record<string | number | symbol, string | undefined>;
|
||||
}) {
|
||||
const locale = getLocale();
|
||||
const t = await getTranslations({ locale, namespace: "otp" });
|
||||
|
||||
const { loginName, authRequestId, sessionId, organization, code, submit } =
|
||||
searchParams;
|
||||
|
||||
@@ -27,23 +31,20 @@ export default async function Page({
|
||||
return (
|
||||
<DynamicTheme branding={branding}>
|
||||
<div className="flex flex-col items-center space-y-4">
|
||||
<h1>Verify 2-Factor</h1>
|
||||
<h1>{t("verify.title")}</h1>
|
||||
{method === "time-based" && (
|
||||
<p className="ztdl-p">Enter the code from your authenticator app.</p>
|
||||
<p className="ztdl-p">{t("verify.totpDescription")}</p>
|
||||
)}
|
||||
{method === "sms" && (
|
||||
<p className="ztdl-p">Enter the code you got on your phone.</p>
|
||||
<p className="ztdl-p">{t("verify.smsDescription")}</p>
|
||||
)}
|
||||
{method === "email" && (
|
||||
<p className="ztdl-p">Enter the code you got via your email.</p>
|
||||
<p className="ztdl-p">{t("verify.emailDescription")}</p>
|
||||
)}
|
||||
|
||||
{!session && (
|
||||
<div className="py-4">
|
||||
<Alert>
|
||||
Could not get the context of the user. Make sure to enter the
|
||||
username first or provide a loginName as searchParam.
|
||||
</Alert>
|
||||
<Alert>{t("error:unknownContext")}</Alert>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
registerTOTP,
|
||||
} from "@/lib/zitadel";
|
||||
import { RegisterTOTPResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||
import { getLocale, getTranslations } from "next-intl/server";
|
||||
import Link from "next/link";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
@@ -22,6 +23,9 @@ export default async function Page({
|
||||
searchParams: Record<string | number | symbol, string | undefined>;
|
||||
params: Record<string | number | symbol, string | undefined>;
|
||||
}) {
|
||||
const locale = getLocale();
|
||||
const t = await getTranslations({ locale, namespace: "otp" });
|
||||
|
||||
const { loginName, organization, sessionId, authRequestId, checkAfter } =
|
||||
searchParams;
|
||||
const { method } = params;
|
||||
@@ -98,13 +102,10 @@ export default async function Page({
|
||||
return (
|
||||
<DynamicTheme branding={branding}>
|
||||
<div className="flex flex-col items-center space-y-4">
|
||||
<h1>Register 2-factor</h1>
|
||||
<h1>{t("set.title")}</h1>
|
||||
{!session && (
|
||||
<div className="py-4">
|
||||
<Alert>
|
||||
Could not get the context of the user. Make sure to enter the
|
||||
username first or provide a loginName as searchParam.
|
||||
</Alert>
|
||||
<Alert>{t("error:unknownContext")}</Alert>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -125,9 +126,7 @@ export default async function Page({
|
||||
|
||||
{totpResponse && "uri" in totpResponse && "secret" in totpResponse ? (
|
||||
<>
|
||||
<p className="ztdl-p">
|
||||
Scan the QR Code or navigate to the URL manually.
|
||||
</p>
|
||||
<p className="ztdl-p">{t("set.totpRegisterDescription")}</p>
|
||||
<div>
|
||||
<TotpRegister
|
||||
uri={totpResponse.uri as string}
|
||||
@@ -160,7 +159,7 @@ export default async function Page({
|
||||
className="self-end"
|
||||
variant={ButtonVariants.Primary}
|
||||
>
|
||||
continue
|
||||
{t("set.submit")}
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { updateSession } from "@/lib/server/session";
|
||||
import { create } from "@zitadel/client";
|
||||
import { RequestChallengesSchema } from "@zitadel/proto/zitadel/session/v2/challenge_pb";
|
||||
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
@@ -35,6 +36,8 @@ export function LoginOTP({
|
||||
method,
|
||||
code,
|
||||
}: Props) {
|
||||
const t = useTranslations("otp");
|
||||
|
||||
const [error, setError] = useState<string>("");
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
|
||||
@@ -191,7 +194,7 @@ export function LoginOTP({
|
||||
<Alert type={AlertType.INFO}>
|
||||
<div className="flex flex-row">
|
||||
<span className="flex-1 mr-auto text-left">
|
||||
Did not get the Code?
|
||||
{t("noCodeReceived")}
|
||||
</span>
|
||||
<button
|
||||
aria-label="Resend OTP Code"
|
||||
@@ -209,7 +212,7 @@ export function LoginOTP({
|
||||
});
|
||||
}}
|
||||
>
|
||||
Resend
|
||||
{t("resendCode")}
|
||||
</button>
|
||||
</div>
|
||||
</Alert>
|
||||
@@ -241,7 +244,7 @@ export function LoginOTP({
|
||||
})}
|
||||
>
|
||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
||||
continue
|
||||
{t("submit")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
import { verifyTOTP } from "@/lib/server-actions";
|
||||
import { useTranslations } from "next-intl";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { QRCodeSVG } from "qrcode.react";
|
||||
@@ -33,6 +34,8 @@ export function TotpRegister({
|
||||
organization,
|
||||
checkAfter,
|
||||
}: Props) {
|
||||
const t = useTranslations("otp");
|
||||
|
||||
const [error, setError] = useState<string>("");
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const router = useRouter();
|
||||
@@ -138,7 +141,7 @@ export function TotpRegister({
|
||||
onClick={handleSubmit(continueWithCode)}
|
||||
>
|
||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
||||
continue
|
||||
{t("set.submit")}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user