ts for cookie, loginname to verification

This commit is contained in:
peintnermax
2024-10-24 10:02:12 +02:00
parent f45c5304a7
commit c4da6fd077
12 changed files with 107 additions and 58 deletions

View File

@@ -1,5 +1,6 @@
"use server";
import { timestampDate, timestampFromMs } from "@zitadel/client";
import { cookies } from "next/headers";
import { LANGUAGE_COOKIE_NAME } from "./i18n";
@@ -11,9 +12,9 @@ export type Cookie = {
token: string;
loginName: string;
organization?: string;
creationDate: string;
expirationDate: string;
changeDate: string;
creationTs: string;
expirationTs: string;
changeTs: string;
authRequestId?: string; // if its linked to an OIDC flow
};
@@ -66,13 +67,17 @@ export async function addSessionToCookie<T>(
// TODO: improve cookie handling
// this replaces the first session (oldest) with the new one
currentSessions = [session].concat(currentSessions.slice(1));
} else {
currentSessions = [session].concat(currentSessions);
}
}
if (cleanup) {
const now = new Date();
const filteredSessions = currentSessions.filter((session) =>
session.expirationDate ? new Date(session.expirationDate) > now : true,
session.expirationTs
? timestampDate(timestampFromMs(Number(session.expirationTs))) > now
: true,
);
return setSessionHttpOnlyCookie(filteredSessions);
} else {
@@ -99,7 +104,9 @@ export async function updateSessionCookie<T>(
if (cleanup) {
const now = new Date();
const filteredSessions = sessions.filter((session) =>
session.expirationDate ? new Date(session.expirationDate) > now : true,
session.expirationTs
? timestampDate(timestampFromMs(Number(session.expirationTs))) > now
: true,
);
return setSessionHttpOnlyCookie(filteredSessions);
} else {
@@ -125,7 +132,9 @@ export async function removeSessionFromCookie<T>(
if (cleanup) {
const now = new Date();
const filteredSessions = reducedSessions.filter((session) =>
session.expirationDate ? new Date(session.expirationDate) > now : true,
session.expirationTs
? timestampDate(timestampFromMs(Number(session.expirationTs))) > now
: true,
);
return setSessionHttpOnlyCookie(filteredSessions);
} else {
@@ -141,10 +150,7 @@ export async function getMostRecentSessionCookie<T>(): Promise<any> {
const sessions: SessionCookie<T>[] = JSON.parse(stringifiedCookie?.value);
const latest = sessions.reduce((prev, current) => {
return new Date(prev.changeDate).getTime() >
new Date(current.changeDate).getTime()
? prev
: current;
return prev.changeTs > current.changeTs ? prev : current;
});
return latest;
@@ -226,8 +232,8 @@ export async function getAllSessionCookieIds<T>(
const now = new Date();
return sessions
.filter((session) =>
session.expirationDate
? new Date(session.expirationDate) > now
session.expirationTs
? timestampDate(timestampFromMs(Number(session.expirationTs))) > now
: true,
)
.map((session) => session.id);
@@ -256,7 +262,9 @@ export async function getAllSessions<T>(
if (cleanup) {
const now = new Date();
return sessions.filter((session) =>
session.expirationDate ? new Date(session.expirationDate) > now : true,
session.expirationTs
? timestampDate(timestampFromMs(Number(session.expirationTs))) > now
: true,
);
} else {
return sessions;
@@ -297,10 +305,7 @@ export async function getMostRecentCookieWithLoginname<T>({
const latest =
filtered && filtered.length
? filtered.reduce((prev, current) => {
return new Date(prev.changeDate).getTime() >
new Date(current.changeDate).getTime()
? prev
: current;
return prev.changeTs > current.changeTs ? prev : current;
})
: undefined;

View File

@@ -20,9 +20,9 @@ type CustomCookieData = {
token: string;
loginName: string;
organization?: string;
creationDate: string;
expirationDate: string;
changeDate: string;
creationTs: string;
expirationTs: string;
changeTs: string;
authRequestId?: string; // if its linked to an OIDC flow
};
@@ -42,13 +42,13 @@ export async function createSessionAndUpdateCookie(
const sessionCookie: CustomCookieData = {
id: createdSession.sessionId,
token: createdSession.sessionToken,
creationDate: response.session.creationDate
creationTs: response.session.creationDate
? `${timestampMs(response.session.creationDate)}`
: "",
expirationDate: response.session.expirationDate
expirationTs: response.session.expirationDate
? `${timestampMs(response.session.expirationDate)}`
: "",
changeDate: response.session.changeDate
changeTs: response.session.changeDate
? `${timestampMs(response.session.changeDate)}`
: "",
loginName: response.session.factors.user.loginName ?? "",
@@ -97,13 +97,13 @@ export async function createSessionForIdpAndUpdateCookie(
const sessionCookie: CustomCookieData = {
id: createdSession.sessionId,
token: createdSession.sessionToken,
creationDate: response.session.creationDate
creationTs: response.session.creationDate
? `${timestampMs(response.session.creationDate)}`
: "",
expirationDate: response.session.expirationDate
expirationTs: response.session.expirationDate
? `${timestampMs(response.session.expirationDate)}`
: "",
changeDate: response.session.changeDate
changeTs: response.session.changeDate
? `${timestampMs(response.session.changeDate)}`
: "",
loginName: response.session.factors.user.loginName ?? "",
@@ -151,10 +151,10 @@ export async function setSessionAndUpdateCookie(
const sessionCookie: CustomCookieData = {
id: recentCookie.id,
token: updatedSession.sessionToken,
creationDate: recentCookie.creationDate,
expirationDate: recentCookie.expirationDate,
creationTs: recentCookie.creationTs,
expirationTs: recentCookie.expirationTs,
// just overwrite the changeDate with the new one
changeDate: updatedSession.details?.changeDate
changeTs: updatedSession.details?.changeDate
? `${timestampMs(updatedSession.details.changeDate)}`
: "",
loginName: recentCookie.loginName,
@@ -174,10 +174,10 @@ export async function setSessionAndUpdateCookie(
const newCookie: CustomCookieData = {
id: sessionCookie.id,
token: updatedSession.sessionToken,
creationDate: sessionCookie.creationDate,
expirationDate: sessionCookie.expirationDate,
creationTs: sessionCookie.creationTs,
expirationTs: sessionCookie.expirationTs,
// just overwrite the changeDate with the new one
changeDate: updatedSession.details?.changeDate
changeTs: updatedSession.details?.changeDate
? `${timestampMs(updatedSession.details.changeDate)}`
: "",
loginName: session.factors?.user?.loginName ?? "",

View File

@@ -20,9 +20,7 @@ type VerifyUserByEmailCommand = {
authRequestId?: string;
};
export async function verifyUserAndCreateSession(
command: VerifyUserByEmailCommand,
) {
export async function sendVerification(command: VerifyUserByEmailCommand) {
const verifyResponse = command.isInvite
? await verifyInviteCode(command.userId, command.code).catch((error) => {
return { error: "Could not verify invite" };

View File

@@ -7,6 +7,7 @@ import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_se
import { headers } from "next/headers";
import { redirect } from "next/navigation";
import { idpTypeToIdentityProviderType, idpTypeToSlug } from "../idp";
import {
getActiveIdentityProviders,
getIDPByID,
@@ -161,6 +162,29 @@ export async function sendLoginname(command: SendLoginnameCommand) {
);
if (!methods.authMethodTypes || !methods.authMethodTypes.length) {
if (
users.result[0].type.case === "human" &&
users.result[0].type.value.email &&
!users.result[0].type.value.email.isVerified
) {
const paramsVerify = new URLSearchParams({
loginName: session.factors?.user?.loginName,
userId: session.factors?.user?.id, // verify needs user id
});
if (command.organization || session.factors?.user?.organizationId) {
paramsVerify.append(
"organization",
command.organization ?? session.factors?.user?.organizationId,
);
}
if (command.authRequestId) {
paramsVerify.append("authRequestId", command.authRequestId);
}
redirect("/verify?" + paramsVerify);
}
return {
error:
"User has no available authentication methods. Contact your administrator to setup authentication for the requested user.",