mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 19:47:34 +00:00
override cookie sameSite settings
This commit is contained in:
@@ -20,7 +20,10 @@ export type Cookie = {
|
||||
|
||||
type SessionCookie<T> = Cookie & T;
|
||||
|
||||
async function setSessionHttpOnlyCookie<T>(sessions: SessionCookie<T>[]) {
|
||||
async function setSessionHttpOnlyCookie<T>(
|
||||
sessions: SessionCookie<T>[],
|
||||
sameSite: boolean | "lax" | "strict" | "none" = true,
|
||||
) {
|
||||
const cookiesList = await cookies();
|
||||
|
||||
return cookiesList.set({
|
||||
@@ -28,6 +31,7 @@ async function setSessionHttpOnlyCookie<T>(sessions: SessionCookie<T>[]) {
|
||||
value: JSON.stringify(sessions),
|
||||
httpOnly: true,
|
||||
path: "/",
|
||||
sameSite,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,10 +46,15 @@ export async function setLanguageCookie(language: string) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function addSessionToCookie<T>(
|
||||
session: SessionCookie<T>,
|
||||
cleanup: boolean = false,
|
||||
): Promise<any> {
|
||||
export async function addSessionToCookie<T>({
|
||||
session,
|
||||
cleanup,
|
||||
sameSite,
|
||||
}: {
|
||||
session: SessionCookie<T>;
|
||||
cleanup?: boolean;
|
||||
sameSite?: boolean | "lax" | "strict" | "none" | undefined;
|
||||
}): Promise<any> {
|
||||
const cookiesList = await cookies();
|
||||
const stringifiedCookie = cookiesList.get("sessions");
|
||||
|
||||
@@ -79,17 +88,23 @@ export async function addSessionToCookie<T>(
|
||||
? timestampDate(timestampFromMs(Number(session.expirationTs))) > now
|
||||
: true,
|
||||
);
|
||||
return setSessionHttpOnlyCookie(filteredSessions);
|
||||
return setSessionHttpOnlyCookie(filteredSessions, sameSite);
|
||||
} else {
|
||||
return setSessionHttpOnlyCookie(currentSessions);
|
||||
return setSessionHttpOnlyCookie(currentSessions, sameSite);
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateSessionCookie<T>(
|
||||
id: string,
|
||||
session: SessionCookie<T>,
|
||||
cleanup: boolean = false,
|
||||
): Promise<any> {
|
||||
export async function updateSessionCookie<T>({
|
||||
id,
|
||||
session,
|
||||
cleanup,
|
||||
sameSite,
|
||||
}: {
|
||||
id: string;
|
||||
session: SessionCookie<T>;
|
||||
cleanup?: boolean;
|
||||
sameSite?: boolean | "lax" | "strict" | "none" | undefined;
|
||||
}): Promise<any> {
|
||||
const cookiesList = await cookies();
|
||||
const stringifiedCookie = cookiesList.get("sessions");
|
||||
|
||||
@@ -108,19 +123,24 @@ export async function updateSessionCookie<T>(
|
||||
? timestampDate(timestampFromMs(Number(session.expirationTs))) > now
|
||||
: true,
|
||||
);
|
||||
return setSessionHttpOnlyCookie(filteredSessions);
|
||||
return setSessionHttpOnlyCookie(filteredSessions, sameSite);
|
||||
} else {
|
||||
return setSessionHttpOnlyCookie(sessions);
|
||||
return setSessionHttpOnlyCookie(sessions, sameSite);
|
||||
}
|
||||
} else {
|
||||
throw "updateSessionCookie<T>: session id now found";
|
||||
}
|
||||
}
|
||||
|
||||
export async function removeSessionFromCookie<T>(
|
||||
session: SessionCookie<T>,
|
||||
cleanup: boolean = false,
|
||||
): Promise<any> {
|
||||
export async function removeSessionFromCookie<T>({
|
||||
session,
|
||||
cleanup,
|
||||
sameSite,
|
||||
}: {
|
||||
session: SessionCookie<T>;
|
||||
cleanup?: boolean;
|
||||
sameSite?: boolean | "lax" | "strict" | "none" | undefined;
|
||||
}): Promise<any> {
|
||||
const cookiesList = await cookies();
|
||||
const stringifiedCookie = cookiesList.get("sessions");
|
||||
|
||||
@@ -136,9 +156,9 @@ export async function removeSessionFromCookie<T>(
|
||||
? timestampDate(timestampFromMs(Number(session.expirationTs))) > now
|
||||
: true,
|
||||
);
|
||||
return setSessionHttpOnlyCookie(filteredSessions);
|
||||
return setSessionHttpOnlyCookie(filteredSessions, sameSite);
|
||||
} else {
|
||||
return setSessionHttpOnlyCookie(reducedSessions);
|
||||
return setSessionHttpOnlyCookie(reducedSessions, sameSite);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -4,6 +4,7 @@ import { addSessionToCookie, updateSessionCookie } from "@/lib/cookies";
|
||||
import {
|
||||
createSessionForUserIdAndIdpIntent,
|
||||
createSessionFromChecks,
|
||||
getSecuritySettings,
|
||||
getSession,
|
||||
setSession,
|
||||
} from "@/lib/zitadel";
|
||||
@@ -65,7 +66,7 @@ export async function createSessionAndUpdateCookie(command: {
|
||||
serviceUrl,
|
||||
sessionId: createdSession.sessionId,
|
||||
sessionToken: createdSession.sessionToken,
|
||||
}).then((response) => {
|
||||
}).then(async (response) => {
|
||||
if (response?.session && response.session?.factors?.user?.loginName) {
|
||||
const sessionCookie: CustomCookieData = {
|
||||
id: createdSession.sessionId,
|
||||
@@ -91,9 +92,14 @@ export async function createSessionAndUpdateCookie(command: {
|
||||
response.session.factors.user.organizationId;
|
||||
}
|
||||
|
||||
return addSessionToCookie(sessionCookie).then(() => {
|
||||
return response.session as Session;
|
||||
});
|
||||
const securitySettings = await getSecuritySettings({ serviceUrl });
|
||||
const sameSite = securitySettings?.embeddedIframe?.enabled
|
||||
? "none"
|
||||
: true;
|
||||
|
||||
await addSessionToCookie({ session: sessionCookie, sameSite });
|
||||
|
||||
return response.session as Session;
|
||||
} else {
|
||||
throw "could not get session or session does not have loginName";
|
||||
}
|
||||
@@ -167,7 +173,10 @@ export async function createSessionForIdpAndUpdateCookie(
|
||||
sessionCookie.organization = session.factors.user.organizationId;
|
||||
}
|
||||
|
||||
return addSessionToCookie(sessionCookie).then(() => {
|
||||
const securitySettings = await getSecuritySettings({ serviceUrl });
|
||||
const sameSite = securitySettings?.embeddedIframe?.enabled ? "none" : true;
|
||||
|
||||
return addSessionToCookie({ session: sessionCookie, sameSite }).then(() => {
|
||||
return session as Session;
|
||||
});
|
||||
}
|
||||
@@ -217,32 +226,44 @@ export async function setSessionAndUpdateCookie(
|
||||
serviceUrl,
|
||||
sessionId: sessionCookie.id,
|
||||
sessionToken: sessionCookie.token,
|
||||
}).then((response) => {
|
||||
if (response?.session && response.session.factors?.user?.loginName) {
|
||||
const { session } = response;
|
||||
const newCookie: CustomCookieData = {
|
||||
id: sessionCookie.id,
|
||||
token: updatedSession.sessionToken,
|
||||
creationTs: sessionCookie.creationTs,
|
||||
expirationTs: sessionCookie.expirationTs,
|
||||
// just overwrite the changeDate with the new one
|
||||
changeTs: updatedSession.details?.changeDate
|
||||
? `${timestampMs(updatedSession.details.changeDate)}`
|
||||
: "",
|
||||
loginName: session.factors?.user?.loginName ?? "",
|
||||
organization: session.factors?.user?.organizationId ?? "",
|
||||
};
|
||||
|
||||
if (sessionCookie.requestId) {
|
||||
newCookie.requestId = sessionCookie.requestId;
|
||||
}
|
||||
|
||||
return updateSessionCookie(sessionCookie.id, newCookie).then(() => {
|
||||
return { challenges: updatedSession.challenges, ...session };
|
||||
});
|
||||
} else {
|
||||
}).then(async (response) => {
|
||||
if (
|
||||
!response?.session ||
|
||||
!response.session.factors?.user?.loginName
|
||||
) {
|
||||
throw "could not get session or session does not have loginName";
|
||||
}
|
||||
|
||||
const { session } = response;
|
||||
const newCookie: CustomCookieData = {
|
||||
id: sessionCookie.id,
|
||||
token: updatedSession.sessionToken,
|
||||
creationTs: sessionCookie.creationTs,
|
||||
expirationTs: sessionCookie.expirationTs,
|
||||
// just overwrite the changeDate with the new one
|
||||
changeTs: updatedSession.details?.changeDate
|
||||
? `${timestampMs(updatedSession.details.changeDate)}`
|
||||
: "",
|
||||
loginName: session.factors?.user?.loginName ?? "",
|
||||
organization: session.factors?.user?.organizationId ?? "",
|
||||
};
|
||||
|
||||
if (sessionCookie.requestId) {
|
||||
newCookie.requestId = sessionCookie.requestId;
|
||||
}
|
||||
|
||||
const securitySettings = await getSecuritySettings({ serviceUrl });
|
||||
const sameSite = securitySettings?.embeddedIframe?.enabled
|
||||
? "none"
|
||||
: true;
|
||||
|
||||
return updateSessionCookie({
|
||||
id: sessionCookie.id,
|
||||
session: newCookie,
|
||||
sameSite,
|
||||
}).then(() => {
|
||||
return { challenges: updatedSession.challenges, ...session };
|
||||
});
|
||||
});
|
||||
} else {
|
||||
throw "Session not be set";
|
||||
|
@@ -4,6 +4,7 @@ import { setSessionAndUpdateCookie } from "@/lib/server/cookie";
|
||||
import {
|
||||
deleteSession,
|
||||
getLoginSettings,
|
||||
getSecuritySettings,
|
||||
humanMFAInitSkipped,
|
||||
listAuthenticationMethodTypes,
|
||||
} from "@/lib/zitadel";
|
||||
@@ -209,8 +210,11 @@ export async function clearSession(options: ClearSessionOptions) {
|
||||
sessionToken: session.token,
|
||||
});
|
||||
|
||||
const securitySettings = await getSecuritySettings({ serviceUrl });
|
||||
const sameSite = securitySettings?.embeddedIframe?.enabled ? "none" : true;
|
||||
|
||||
if (deletedSession) {
|
||||
return removeSessionFromCookie(session);
|
||||
return removeSessionFromCookie({ session, sameSite });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,9 +234,12 @@ export async function cleanupSession({ sessionId }: CleanupSessionCommand) {
|
||||
sessionToken: sessionCookie.token,
|
||||
});
|
||||
|
||||
const securitySettings = await getSecuritySettings({ serviceUrl });
|
||||
const sameSite = securitySettings?.embeddedIframe?.enabled ? "none" : true;
|
||||
|
||||
if (!deleteResponse) {
|
||||
throw new Error("Could not delete session");
|
||||
}
|
||||
|
||||
return removeSessionFromCookie(sessionCookie);
|
||||
return removeSessionFromCookie({ session: sessionCookie, sameSite });
|
||||
}
|
||||
|
Reference in New Issue
Block a user