initial param for password set page, fix cookie overflow

This commit is contained in:
peintnermax
2024-10-22 14:01:11 +02:00
parent 8a88e939e7
commit c626dd53e8
10 changed files with 104 additions and 69 deletions

View File

@@ -19,7 +19,7 @@ export default async function Page({
const t = await getTranslations({ locale, namespace: "password" });
const tError = await getTranslations({ locale, namespace: "error" });
const { loginName, organization, authRequestId, code } = searchParams;
const { loginName, organization, authRequestId } = searchParams;
// also allow no session to be found (ignoreUnkownUsername)
const sessionFactors = await loadMostRecentSession({

View File

@@ -22,7 +22,8 @@ export default async function Page({
const t = await getTranslations({ locale, namespace: "password" });
const tError = await getTranslations({ locale, namespace: "error" });
const { userId, loginName, organization, authRequestId, code } = searchParams;
const { userId, loginName, organization, authRequestId, code, initial } =
searchParams;
// also allow no session to be found (ignoreUnkownUsername)
let session: Session | undefined;
@@ -81,7 +82,7 @@ export default async function Page({
></UserAvatar>
) : null}
<Alert type={AlertType.INFO}>{t("set.codeSent")}</Alert>
{!initial && <Alert type={AlertType.INFO}>{t("set.codeSent")}</Alert>}
{passwordComplexity &&
(loginName ?? user?.preferredLoginName) &&
@@ -93,6 +94,7 @@ export default async function Page({
authRequestId={authRequestId}
organization={organization}
passwordComplexitySettings={passwordComplexity}
codeRequired={!(initial === "true")}
/>
) : (
<div className="py-4">

View File

@@ -104,13 +104,13 @@ export const U2F = (alreadyAdded: boolean, link: string) => {
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
strokeWidth="1.5"
stroke="currentColor"
className="w-8 h-8 mr-4"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
d="M7.864 4.243A7.5 7.5 0 0119.5 10.5c0 2.92-.556 5.709-1.568 8.268M5.742 6.364A7.465 7.465 0 004.5 10.5a7.464 7.464 0 01-1.15 3.993m1.989 3.559A11.209 11.209 0 008.25 10.5a3.75 3.75 0 117.5 0c0 .527-.021 1.049-.064 1.565M12 10.5a14.94 14.94 0 01-3.6 9.75m6.633-4.596a18.666 18.666 0 01-2.485 5.33"
/>
</svg>
@@ -143,8 +143,8 @@ export const EMAIL = (alreadyAdded: boolean, link: string) => {
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75"
/>
</svg>

View File

@@ -12,7 +12,6 @@ import { create } from "@zitadel/client";
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { FieldValues, useForm } from "react-hook-form";
import { Alert } from "./alert";
@@ -57,8 +56,6 @@ export function ChangePasswordForm({
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string>("");
const router = useRouter();
async function submitChange(values: Inputs) {
setLoading(true);
const changeResponse = await setMyPassword({

View File

@@ -35,6 +35,7 @@ type Props = {
userId: string;
organization?: string;
authRequestId?: string;
codeRequired: boolean;
};
export function SetPasswordForm({
@@ -44,6 +45,7 @@ export function SetPasswordForm({
loginName,
userId,
code,
codeRequired,
}: Props) {
const t = useTranslations("password");
@@ -59,11 +61,17 @@ export function SetPasswordForm({
async function submitRegister(values: Inputs) {
setLoading(true);
const changeResponse = await changePassword({
let payload: { userId: string; password: string; code?: string } = {
userId: userId,
password: values.password,
code: values.code,
}).catch(() => {
};
// this is not required for initial password setup
if (codeRequired) {
payload = { ...payload, code: values.code };
}
const changeResponse = await changePassword(payload).catch(() => {
setError("Could not register user");
});
@@ -94,7 +102,8 @@ export function SetPasswordForm({
password: { password: values.password },
}),
authRequestId,
}).catch(() => {
}).catch((error) => {
console.error("verifyerror", error);
setLoading(false);
setError("Could not verify password");
return;
@@ -109,23 +118,6 @@ export function SetPasswordForm({
) {
setError(passwordResponse.error);
}
// // skip verification for now as it is an app based flow
// // return router.push(`/verify?` + params);
// // check for mfa force to continue with mfa setup
// if (authRequestId && changeResponse.sessionId) {
// if (authRequestId) {
// params.append("authRequest", authRequestId);
// }
// return router.push(`/login?` + params);
// } else {
// if (authRequestId) {
// params.append("authRequestId", authRequestId);
// }
// return router.push(`/signedin?` + params);
// }
}
const { errors } = formState;
@@ -152,6 +144,7 @@ export function SetPasswordForm({
return (
<form className="w-full">
<div className="pt-4 grid grid-cols-1 gap-4 mb-4">
{codeRequired && (
<div className="flex flex-row items-end">
<div className="flex-1">
<TextInput
@@ -165,12 +158,14 @@ export function SetPasswordForm({
error={errors.code?.message as string}
/>
</div>
<div className="ml-4 mb-1">
<Button variant={ButtonVariants.Secondary}>
{t("set.resend")}
</Button>
</div>
</div>
)}
<div className="">
<TextInput
type="password"

View File

@@ -65,7 +65,13 @@ export function VerifyEmailForm({
const router = useRouter();
const params = new URLSearchParams({});
const params = new URLSearchParams({
userId: userId,
});
if (isInvite) {
params.append("initial", "true");
}
if (loginName) {
params.append("loginName", loginName);
@@ -121,7 +127,10 @@ export function VerifyEmailForm({
}
// if auth methods fall trough, we complete to login
const params = new URLSearchParams({});
const params = new URLSearchParams({
userId: userId,
initial: "true", // defines that a code is not required and is therefore not shown in the UI
});
if (organization) {
params.set("organization", organization);

View File

@@ -3,6 +3,9 @@
import { cookies } from "next/headers";
import { LANGUAGE_COOKIE_NAME } from "./i18n";
// TODO: improve this to handle overflow
export const MAX_COOKIE_SIZE = 4096;
export type Cookie = {
id: string;
token: string;
@@ -56,7 +59,13 @@ export async function addSessionToCookie<T>(
if (index > -1) {
currentSessions[index] = session;
} else {
currentSessions = [...currentSessions, session];
const temp = [...currentSessions, session];
if (temp.length > MAX_COOKIE_SIZE) {
// TODO: improve cookie handling
// this replaces the first session (oldest) with the new one
currentSessions = [session].concat(currentSessions.slice(1));
}
}
if (cleanup) {

View File

@@ -169,7 +169,6 @@ export const PROVIDER_MAPPING: {
} = {
[IdentityProviderType.GOOGLE]: (idp: IDPInformation) => {
const rawInfo = idp.rawInformation as OIDC_USER;
console.log(rawInfo);
return create(AddHumanUserRequestSchema, {
username: idp.userName,

View File

@@ -71,8 +71,6 @@ export async function sendPassword(command: UpdateSessionCommand) {
organizationId: command.organization,
});
console.log(users);
if (users.details?.totalResult == BigInt(1) && users.result[0].userId) {
user = users.result[0];
@@ -89,7 +87,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
}
// this is a fake error message to hide that the user does not even exist
return { error: "Could not verify password!" };
return { error: "Could not verify password" };
} else {
session = await setSessionAndUpdateCookie(
sessionCookie,
@@ -274,7 +272,7 @@ export async function sendPassword(command: UpdateSessionCommand) {
}
export async function changePassword(command: {
code: string;
code?: string;
userId: string;
password: string;
}) {

View File

@@ -13,6 +13,7 @@ import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
import { IDPInformation } from "@zitadel/proto/zitadel/user/v2/idp_pb";
import {
RetrieveIdentityProviderIntentRequest,
SetPasswordRequestSchema,
VerifyPasskeyRegistrationRequest,
VerifyU2FRegistrationRequest,
} from "@zitadel/proto/zitadel/user/v2/user_service_pb";
@@ -315,7 +316,6 @@ export async function verifyInviteCode(
}
export async function resendInviteCode(userId: string) {
console.log("resetInit");
return userService.resendInviteCode({ userId }, {});
}
@@ -580,24 +580,50 @@ export async function passwordReset(userId: string, host: string | null) {
);
}
/**
*
* @param userId userId of the user to set the password for
* @param password the new password
* @param code optional if the password should be set with a code (reset), no code for initial setup of password
* @returns
*/
export async function setPassword(
userId: string,
password: string,
code: string,
code?: string,
) {
return userService.setPassword(
{
let payload = create(SetPasswordRequestSchema, {
userId,
newPassword: {
password,
},
});
// check if the user has no password set in order to set a password
if (!code) {
const authmethods = await listAuthenticationMethodTypes(userId);
// if the user has no authmethods set, we can set a password otherwise we need a code
if (
!authmethods ||
!authmethods.authMethodTypes ||
authmethods.authMethodTypes.length === 0
) {
return { error: "Provide a code to set a password" };
}
}
if (code) {
payload = {
...payload,
verification: {
case: "verificationCode",
value: code,
},
},
{},
);
};
}
return userService.setPassword(payload, {});
}
/**