mirror of
https://github.com/fosrl/pangolin.git
synced 2025-05-13 13:50:40 +01:00
append timestamp to cookie name to prevent redirect loops
This commit is contained in:
parent
f37be774a6
commit
f2a14e6a36
2 changed files with 58 additions and 15 deletions
|
@ -170,16 +170,17 @@ export function serializeResourceSessionCookie(
|
||||||
isHttp: boolean = false,
|
isHttp: boolean = false,
|
||||||
expiresAt?: Date
|
expiresAt?: Date
|
||||||
): string {
|
): string {
|
||||||
|
const now = new Date().getTime();
|
||||||
if (!isHttp) {
|
if (!isHttp) {
|
||||||
if (expiresAt === undefined) {
|
if (expiresAt === undefined) {
|
||||||
return `${cookieName}_s=${token}; HttpOnly; SameSite=Lax; Path=/; Secure; Domain=${"." + domain}`;
|
return `${cookieName}_s.${now}=${token}; HttpOnly; SameSite=Lax; Path=/; Secure; Domain=${"." + domain}`;
|
||||||
}
|
}
|
||||||
return `${cookieName}_s=${token}; HttpOnly; SameSite=Lax; Expires=${expiresAt.toUTCString()}; Path=/; Secure; Domain=${"." + domain}`;
|
return `${cookieName}_s.${now}=${token}; HttpOnly; SameSite=Lax; Expires=${expiresAt.toUTCString()}; Path=/; Secure; Domain=${"." + domain}`;
|
||||||
} else {
|
} else {
|
||||||
if (expiresAt === undefined) {
|
if (expiresAt === undefined) {
|
||||||
return `${cookieName}=${token}; HttpOnly; SameSite=Lax; Path=/; Domain=${"." + domain}`;
|
return `${cookieName}.${now}=${token}; HttpOnly; SameSite=Lax; Path=/; Domain=${"." + domain}`;
|
||||||
}
|
}
|
||||||
return `${cookieName}=${token}; HttpOnly; SameSite=Lax; Expires=${expiresAt.toUTCString()}; Path=/; Domain=${"." + domain}`;
|
return `${cookieName}.${now}=${token}; HttpOnly; SameSite=Lax; Expires=${expiresAt.toUTCString()}; Path=/; Domain=${"." + domain}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,12 +229,10 @@ export async function verifyResourceSession(
|
||||||
return notAllowed(res);
|
return notAllowed(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceSessionToken =
|
const resourceSessionToken = extractResourceSessionToken(
|
||||||
sessions[
|
sessions,
|
||||||
`${config.getRawConfig().server.session_cookie_name}${
|
resource.ssl
|
||||||
resource.ssl ? "_s" : ""
|
);
|
||||||
}`
|
|
||||||
];
|
|
||||||
|
|
||||||
if (resourceSessionToken) {
|
if (resourceSessionToken) {
|
||||||
const sessionCacheKey = `session:${resourceSessionToken}`;
|
const sessionCacheKey = `session:${resourceSessionToken}`;
|
||||||
|
@ -354,6 +352,50 @@ export async function verifyResourceSession(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extractResourceSessionToken(
|
||||||
|
sessions: Record<string, string>,
|
||||||
|
ssl: boolean
|
||||||
|
) {
|
||||||
|
const prefix = `${config.getRawConfig().server.session_cookie_name}${
|
||||||
|
ssl ? "_s" : ""
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const all: { cookieName: string; token: string; priority: number }[] =
|
||||||
|
[];
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(sessions)) {
|
||||||
|
const parts = key.split(".");
|
||||||
|
const timestamp = parts[parts.length - 1];
|
||||||
|
|
||||||
|
// check if string is only numbers
|
||||||
|
if (!/^\d+$/.test(timestamp)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cookie name is the key without the timestamp
|
||||||
|
const cookieName = key.slice(0, -timestamp.length - 1);
|
||||||
|
|
||||||
|
if (cookieName === prefix) {
|
||||||
|
all.push({
|
||||||
|
cookieName,
|
||||||
|
token: value,
|
||||||
|
priority: parseInt(timestamp)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort by priority in desc order
|
||||||
|
all.sort((a, b) => b.priority - a.priority);
|
||||||
|
|
||||||
|
const latest = all[0];
|
||||||
|
|
||||||
|
if (!latest) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return latest.token;
|
||||||
|
}
|
||||||
|
|
||||||
function notAllowed(res: Response, redirectUrl?: string) {
|
function notAllowed(res: Response, redirectUrl?: string) {
|
||||||
const data = {
|
const data = {
|
||||||
data: { valid: false, redirectUrl },
|
data: { valid: false, redirectUrl },
|
||||||
|
@ -612,21 +654,21 @@ export function isPathAllowed(pattern: string, path: string): boolean {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`${indent}Found in-segment wildcard in "${currentPatternPart}"`
|
`${indent}Found in-segment wildcard in "${currentPatternPart}"`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Convert the pattern segment to a regex pattern
|
// Convert the pattern segment to a regex pattern
|
||||||
const regexPattern = currentPatternPart
|
const regexPattern = currentPatternPart
|
||||||
.replace(/\*/g, ".*") // Replace * with .* for regex wildcard
|
.replace(/\*/g, ".*") // Replace * with .* for regex wildcard
|
||||||
.replace(/\?/g, "."); // Replace ? with . for single character wildcard if needed
|
.replace(/\?/g, "."); // Replace ? with . for single character wildcard if needed
|
||||||
|
|
||||||
const regex = new RegExp(`^${regexPattern}$`);
|
const regex = new RegExp(`^${regexPattern}$`);
|
||||||
|
|
||||||
if (regex.test(currentPathPart)) {
|
if (regex.test(currentPathPart)) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`${indent}Segment with wildcard matches: "${currentPatternPart}" matches "${currentPathPart}"`
|
`${indent}Segment with wildcard matches: "${currentPatternPart}" matches "${currentPathPart}"`
|
||||||
);
|
);
|
||||||
return matchSegments(patternIndex + 1, pathIndex + 1);
|
return matchSegments(patternIndex + 1, pathIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`${indent}Segment with wildcard mismatch: "${currentPatternPart}" doesn't match "${currentPathPart}"`
|
`${indent}Segment with wildcard mismatch: "${currentPatternPart}" doesn't match "${currentPathPart}"`
|
||||||
);
|
);
|
||||||
|
@ -651,4 +693,4 @@ export function isPathAllowed(pattern: string, path: string): boolean {
|
||||||
const result = matchSegments(0, 0);
|
const result = matchSegments(0, 0);
|
||||||
logger.debug(`Final result: ${result}`);
|
logger.debug(`Final result: ${result}`);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue