You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.8 KiB
TypeScript

import { Request, Response } from 'express';
import { CookieConfig } from '../types/auth.types';
/**
* Manages cookie operations for authentication
*/
export class CookieManager {
private readonly config: CookieConfig;
constructor(config: CookieConfig) {
this.config = {
domain: config.domain,
sessionName: config.sessionName || 'sid',
refreshName: config.refreshName || 'rid',
secureCookie: config.secureCookie !== false,
sameSite: config.sameSite || 'lax',
httpOnly: config.httpOnly !== false,
sessionTTL: config.sessionTTL || 7200, // 2 hours
refreshTTL: config.refreshTTL || 604800 // 7 days
};
}
/**
* Get standard cookie options
*/
private getCookieOptions(maxAge?: number) {
return {
domain: this.config.domain,
httpOnly: this.config.httpOnly,
secure: this.config.secureCookie,
sameSite: this.config.sameSite as 'strict' | 'lax' | 'none',
path: '/',
...(maxAge && { maxAge })
};
}
/**
* Set authentication cookies (session and optionally refresh)
*/
setAuthCookies(res: Response, { sessionId, refreshId }: { sessionId: string; refreshId?: string }) {
// Set session cookie
res.cookie(
this.config.sessionName,
sessionId,
this.getCookieOptions((this.config.sessionTTL || 7200) * 1000)
);
// Set refresh cookie if provided
if (refreshId && this.config.refreshName) {
res.cookie(
this.config.refreshName,
refreshId,
this.getCookieOptions((this.config.refreshTTL || 604800) * 1000)
);
}
}
/**
* Clear authentication cookies
*/
clearAuthCookies(res: Response) {
res.clearCookie(this.config.sessionName, this.getCookieOptions());
if (this.config.refreshName) {
res.clearCookie(this.config.refreshName, this.getCookieOptions());
}
}
/**
* Extract cookies from request
*/
extractCookies(req: Request): { sessionId?: string; refreshId?: string } {
return {
sessionId: req.cookies?.[this.config.sessionName],
refreshId: this.config.refreshName ? req.cookies?.[this.config.refreshName] : undefined
};
}
/**
* Check if request has valid session cookie
*/
hasSessionCookie(req: Request): boolean {
return !!req.cookies?.[this.config.sessionName];
}
/**
* Check if request has valid refresh cookie
*/
hasRefreshCookie(req: Request): boolean {
return !!(this.config.refreshName && req.cookies?.[this.config.refreshName]);
}
/**
* Get session ID from request
*/
getSessionId(req: Request): string | undefined {
return req.cookies?.[this.config.sessionName];
}
/**
* Get refresh ID from request
*/
getRefreshId(req: Request): string | undefined {
return this.config.refreshName ? req.cookies?.[this.config.refreshName] : undefined;
}
}