1
This commit is contained in:
96
server-node/src/auth/refreshSessionCookie.ts
Normal file
96
server-node/src/auth/refreshSessionCookie.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import crypto from 'node:crypto';
|
||||
|
||||
import type { Request, Response } from 'express';
|
||||
|
||||
import type { AppConfig } from '../config.js';
|
||||
|
||||
export type RefreshSessionRequestContext = {
|
||||
clientType: string;
|
||||
userAgent: string | null;
|
||||
ip: string | null;
|
||||
};
|
||||
|
||||
function buildCookieParts(
|
||||
config: AppConfig,
|
||||
value: string,
|
||||
options: {
|
||||
maxAgeSeconds: number;
|
||||
},
|
||||
) {
|
||||
const parts = [
|
||||
`${config.authSession.refreshCookieName}=${encodeURIComponent(value)}`,
|
||||
`Path=${config.authSession.refreshCookiePath}`,
|
||||
'HttpOnly',
|
||||
`SameSite=${config.authSession.refreshCookieSameSite}`,
|
||||
`Max-Age=${Math.max(0, Math.floor(options.maxAgeSeconds))}`,
|
||||
];
|
||||
|
||||
if (config.authSession.refreshCookieSecure) {
|
||||
parts.push('Secure');
|
||||
}
|
||||
|
||||
return parts.join('; ');
|
||||
}
|
||||
|
||||
export function hashRefreshSessionToken(token: string) {
|
||||
return crypto.createHash('sha256').update(token).digest('hex');
|
||||
}
|
||||
|
||||
export function createRefreshSessionToken() {
|
||||
return crypto.randomBytes(32).toString('base64url');
|
||||
}
|
||||
|
||||
export function setRefreshSessionCookie(
|
||||
response: Response,
|
||||
config: AppConfig,
|
||||
token: string,
|
||||
maxAgeSeconds: number,
|
||||
) {
|
||||
response.setHeader(
|
||||
'Set-Cookie',
|
||||
buildCookieParts(config, token, {
|
||||
maxAgeSeconds,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function clearRefreshSessionCookie(response: Response, config: AppConfig) {
|
||||
response.setHeader(
|
||||
'Set-Cookie',
|
||||
buildCookieParts(config, '', {
|
||||
maxAgeSeconds: 0,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function readRefreshSessionToken(request: Request, config: AppConfig) {
|
||||
const cookieHeader = request.header('cookie')?.trim() || '';
|
||||
if (!cookieHeader) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const cookieEntries = cookieHeader.split(';');
|
||||
for (const entry of cookieEntries) {
|
||||
const [rawName, ...valueParts] = entry.split('=');
|
||||
const name = rawName?.trim();
|
||||
if (name !== config.authSession.refreshCookieName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const rawValue = valueParts.join('=').trim();
|
||||
return rawValue ? decodeURIComponent(rawValue) : '';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
export function buildRefreshSessionRequestContext(
|
||||
request: Request,
|
||||
): RefreshSessionRequestContext {
|
||||
const userAgent = request.header('user-agent')?.trim() || null;
|
||||
return {
|
||||
clientType: 'browser',
|
||||
userAgent,
|
||||
ip: request.ip || null,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user