feat: add cookie-based auth utilities for browser user flows
This commit is contained in:
60
src/lib/auth.js
Normal file
60
src/lib/auth.js
Normal file
@@ -0,0 +1,60 @@
|
||||
"use strict";
|
||||
|
||||
const COOKIE_NAME = "xartaudio_user";
|
||||
|
||||
function parseCookies(cookieHeader) {
|
||||
if (!cookieHeader) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return String(cookieHeader)
|
||||
.split(";")
|
||||
.map((part) => part.trim())
|
||||
.filter(Boolean)
|
||||
.reduce((acc, pair) => {
|
||||
const eq = pair.indexOf("=");
|
||||
if (eq <= 0) {
|
||||
return acc;
|
||||
}
|
||||
const key = pair.slice(0, eq).trim();
|
||||
const value = pair.slice(eq + 1).trim();
|
||||
acc[key] = decodeURIComponent(value);
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function serializeUserCookie(userId, maxAgeSeconds) {
|
||||
if (!userId) {
|
||||
throw new Error("user_id_required");
|
||||
}
|
||||
|
||||
const encoded = encodeURIComponent(String(userId));
|
||||
const maxAge = Number.isInteger(maxAgeSeconds) && maxAgeSeconds > 0
|
||||
? maxAgeSeconds
|
||||
: 60 * 60 * 24 * 30;
|
||||
|
||||
return `${COOKIE_NAME}=${encoded}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${maxAge}`;
|
||||
}
|
||||
|
||||
function clearUserCookie() {
|
||||
return `${COOKIE_NAME}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`;
|
||||
}
|
||||
|
||||
function getAuthenticatedUserId(headers) {
|
||||
const safeHeaders = headers || {};
|
||||
|
||||
if (safeHeaders["x-user-id"]) {
|
||||
return safeHeaders["x-user-id"];
|
||||
}
|
||||
|
||||
const cookies = parseCookies(safeHeaders.cookie || "");
|
||||
return cookies[COOKIE_NAME] || null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
COOKIE_NAME,
|
||||
parseCookies,
|
||||
serializeUserCookie,
|
||||
clearUserCookie,
|
||||
getAuthenticatedUserId,
|
||||
};
|
||||
Reference in New Issue
Block a user