fix otp login

This commit is contained in:
peintnermax
2024-09-05 14:49:48 +02:00
parent 02ea2fc00e
commit 4a1c2337ef
3 changed files with 56 additions and 90 deletions

View File

@@ -103,38 +103,6 @@ export async function updateSession(options: UpdateSessionCommand) {
const recent = await sessionPromise; const recent = await sessionPromise;
// if (
// (recent &&
// challenges &&
// challenges.otpEmail &&
// !challenges.otpEmail?.deliveryType) ||
// (challenges?.otpSms && !challenges.otpSms.returnCode)
// ) {
// const sessionResponse = await getSession(recent.id, recent.token);
// if (sessionResponse && sessionResponse?.session?.factors?.user?.id) {
// const userResponse = await getUserByID(
// sessionResponse.session.factors.user.id,
// );
// const humanUser =
// userResponse.user?.type.case === "human"
// ? userResponse.user.type.value
// : undefined;
// if (!challenges.otpEmail && humanUser?.email?.email) {
// challenges = create(RequestChallengesSchema, {
// otpEmail: { deliveryType: { case: "sendCode", value: {} } },
// });
// }
// if (!challenges.otpEmail && humanUser?.email?.email) {
// challenges = create(RequestChallengesSchema, {
// otpSms: { returnCode: true },
// });
// }
// }
// }
const session = await setSessionAndUpdateCookie( const session = await setSessionAndUpdateCookie(
recent, recent,
checks, checks,

View File

@@ -1,7 +1,9 @@
"use client"; "use client";
import { ChallengesJson } from "@zitadel/proto/zitadel/session/v2/challenge_pb"; import {
import { ChecksJson } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; ChecksJson,
ChecksSchema,
} from "@zitadel/proto/zitadel/session/v2/session_service_pb";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
@@ -10,6 +12,9 @@ import BackButton from "./BackButton";
import { Button, ButtonVariants } from "./Button"; import { Button, ButtonVariants } from "./Button";
import { TextInput } from "./Input"; import { TextInput } from "./Input";
import { Spinner } from "./Spinner"; import { Spinner } from "./Spinner";
import { create } from "@zitadel/client";
import { RequestChallengesSchema } from "@zitadel/proto/zitadel/session/v2/challenge_pb";
import { updateSession } from "@/lib/server/session";
// either loginName or sessionId must be provided // either loginName or sessionId must be provided
type Props = { type Props = {
@@ -63,36 +68,35 @@ export default function LoginOTP({
}, []); }, []);
async function updateSessionForOTPChallenge() { async function updateSessionForOTPChallenge() {
const challenges: ChallengesJson = {}; let challenges;
if (method === "email") { if (method === "email") {
challenges.otpEmail = ""; challenges = create(RequestChallengesSchema, {
otpEmail: { deliveryType: { case: "sendCode", value: {} } },
});
} }
if (method === "sms") { if (method === "sms") {
challenges.otpSms = ""; challenges = create(RequestChallengesSchema, {
otpSms: { returnCode: true },
});
} }
setLoading(true); setLoading(true);
const res = await fetch("/api/session", { const response = await updateSession({
method: "PUT", loginName,
headers: { sessionId,
"Content-Type": "application/json", organization,
}, challenges,
body: JSON.stringify({ authRequestId,
loginName, }).catch((error) => {
sessionId, setError(error.message ?? "Could not request OTP challenge");
organization, setLoading(false);
challenges,
authRequestId,
}),
}); });
setLoading(false); setLoading(false);
if (!res.ok) {
const error = await res.json(); return response;
throw error.details.details;
}
return res.json();
} }
async function submitCode(values: Inputs, organization?: string) { async function submitCode(values: Inputs, organization?: string) {
@@ -111,41 +115,38 @@ export default function LoginOTP({
body.authRequestId = authRequestId; body.authRequestId = authRequestId;
} }
const checks: ChecksJson = {}; let checks;
if (method === "sms") { if (method === "sms") {
checks.otpSms = { code: values.code }; checks = create(ChecksSchema, {
otpSms: { code: values.code },
});
} }
if (method === "email") { if (method === "email") {
checks.otpEmail = { code: values.code }; checks = create(ChecksSchema, {
otpEmail: { code: values.code },
});
} }
if (method === "time-based") { if (method === "time-based") {
checks.totp = { code: values.code }; checks = create(ChecksSchema, {
totp: { code: values.code },
});
} }
const res = await fetch("/api/session", { const response = await updateSession({
method: "PUT", loginName,
headers: { sessionId,
"Content-Type": "application/json", organization,
}, checks,
body: JSON.stringify({ authRequestId,
loginName, }).catch((error) => {
sessionId, setError(error.message ?? "Could not verify OTP code");
organization, setLoading(false);
checks,
authRequestId,
}),
}); });
setLoading(false); setLoading(false);
if (!res.ok) {
const response = await res.json();
setError(response.details.details ?? "An internal error occurred"); return response;
return Promise.reject(
response.details.details ?? "An internal error occurred",
);
}
return res.json();
} }
function setCodeAndContinue(values: Inputs, organization?: string) { function setCodeAndContinue(values: Inputs, organization?: string) {
@@ -162,16 +163,13 @@ export default function LoginOTP({
return router.push(`/login?` + params); return router.push(`/login?` + params);
} else { } else {
const params = new URLSearchParams( const params = new URLSearchParams();
authRequestId if (response?.factors?.user?.loginName) {
? { params.append("loginName", response.factors.user.loginName);
loginName: response.factors.user.loginName, }
authRequestId, if (authRequestId) {
} params.append("authRequestId", authRequestId);
: { }
loginName: response.factors.user.loginName,
},
);
if (organization) { if (organization) {
params.append("organization", organization); params.append("organization", organization);
@@ -182,8 +180,6 @@ export default function LoginOTP({
}); });
} }
const { errors } = formState;
return ( return (
<form className="w-full"> <form className="w-full">
{["email", "sms"].includes(method) && ( {["email", "sms"].includes(method) && (

View File

@@ -108,6 +108,8 @@ export default function PasswordForm({
m !== AuthenticationMethodType.PASSKEY, m !== AuthenticationMethodType.PASSKEY,
); );
console.log(availableSecondFactors, loginSettings);
if (availableSecondFactors.length == 1) { if (availableSecondFactors.length == 1) {
const params = new URLSearchParams({ const params = new URLSearchParams({
loginName: submitted.factors.user.loginName, loginName: submitted.factors.user.loginName,