otp url template, reset with authrequest

This commit is contained in:
Max Peintner
2024-11-28 16:56:46 +01:00
parent 4be67c2235
commit ba3359ff51
6 changed files with 31 additions and 5 deletions

View File

@@ -5,6 +5,7 @@ import { UserAvatar } from "@/components/user-avatar";
import { loadMostRecentSession } from "@/lib/session"; import { loadMostRecentSession } from "@/lib/session";
import { getBrandingSettings, getLoginSettings } from "@/lib/zitadel"; import { getBrandingSettings, getLoginSettings } from "@/lib/zitadel";
import { getLocale, getTranslations } from "next-intl/server"; import { getLocale, getTranslations } from "next-intl/server";
import { headers } from "next/headers";
export default async function Page(props: { export default async function Page(props: {
searchParams: Promise<Record<string | number | symbol, string | undefined>>; searchParams: Promise<Record<string | number | symbol, string | undefined>>;
@@ -30,6 +31,8 @@ export default async function Page(props: {
const loginSettings = await getLoginSettings(organization); const loginSettings = await getLoginSettings(organization);
const host = (await headers()).get("host");
return ( return (
<DynamicTheme branding={branding}> <DynamicTheme branding={branding}>
<div className="flex flex-col items-center space-y-4"> <div className="flex flex-col items-center space-y-4">
@@ -67,6 +70,8 @@ export default async function Page(props: {
organization={organization} organization={organization}
method={method} method={method}
loginSettings={loginSettings} loginSettings={loginSettings}
host={host}
code={code}
></LoginOTP> ></LoginOTP>
)} )}
</div> </div>

View File

@@ -25,6 +25,7 @@ type Props = {
method: string; method: string;
code?: string; code?: string;
loginSettings?: LoginSettings; loginSettings?: LoginSettings;
host: string | null;
}; };
type Inputs = { type Inputs = {
@@ -39,6 +40,7 @@ export function LoginOTP({
method, method,
code, code,
loginSettings, loginSettings,
host,
}: Props) { }: Props) {
const t = useTranslations("otp"); const t = useTranslations("otp");
@@ -76,7 +78,18 @@ export function LoginOTP({
if (method === "email") { if (method === "email") {
challenges = create(RequestChallengesSchema, { challenges = create(RequestChallengesSchema, {
otpEmail: { deliveryType: { case: "sendCode", value: {} } }, otpEmail: {
deliveryType: {
case: "sendCode",
value: host
? {
urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/otp/method=${method}?code={{.Code}}&userId={{.UserID}}&sessionId={{.SessionID}}&organization={{.OrgID}}` +
(authRequestId ? `&authRequestId=${authRequestId}` : ""),
}
: {},
},
},
}); });
} }

View File

@@ -86,6 +86,7 @@ export function PasswordForm({
const response = await resetPassword({ const response = await resetPassword({
loginName, loginName,
organization, organization,
authRequestId,
}) })
.catch(() => { .catch(() => {
setError("Could not reset password"); setError("Could not reset password");

View File

@@ -102,7 +102,7 @@ export function SessionItem({
/> />
</div> </div>
<div className="flex flex-col overflow-hidden"> <div className="flex flex-col items-start overflow-hidden">
<span className="">{session.factors?.user?.displayName}</span> <span className="">{session.factors?.user?.displayName}</span>
<span className="text-xs opacity-80 text-ellipsis"> <span className="text-xs opacity-80 text-ellipsis">
{session.factors?.user?.loginName} {session.factors?.user?.loginName}

View File

@@ -27,6 +27,7 @@ import { getSessionCookieByLoginName } from "../cookies";
type ResetPasswordCommand = { type ResetPasswordCommand = {
loginName: string; loginName: string;
organization?: string; organization?: string;
authRequestId?: string;
}; };
export async function resetPassword(command: ResetPasswordCommand) { export async function resetPassword(command: ResetPasswordCommand) {
@@ -46,7 +47,7 @@ export async function resetPassword(command: ResetPasswordCommand) {
} }
const userId = users.result[0].userId; const userId = users.result[0].userId;
return passwordReset(userId, host); return passwordReset(userId, host, command.authRequestId);
} }
export type UpdateSessionCommand = { export type UpdateSessionCommand = {

View File

@@ -504,7 +504,11 @@ export function createUser(
* @param userId the id of the user where the email should be set * @param userId the id of the user where the email should be set
* @returns the newly set email * @returns the newly set email
*/ */
export async function passwordReset(userId: string, host: string | null) { export async function passwordReset(
userId: string,
host: string | null,
authRequestId?: string,
) {
let medium = create(SendPasswordResetLinkSchema, { let medium = create(SendPasswordResetLinkSchema, {
notificationType: NotificationType.Email, notificationType: NotificationType.Email,
}); });
@@ -512,7 +516,9 @@ export async function passwordReset(userId: string, host: string | null) {
if (host) { if (host) {
medium = { medium = {
...medium, ...medium,
urlTemplate: `${host.includes("localhost") ? "http://" : "https://"}${host}/password/set?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}`, urlTemplate:
`${host.includes("localhost") ? "http://" : "https://"}${host}/password/set?code={{.Code}}&userId={{.UserID}}&organization={{.OrgID}}` +
(authRequestId ? `&authRequestId=${authRequestId}` : ""),
}; };
} }