allow controlling cors from config and add cors middleware to traefik

This commit is contained in:
Milo Schwartz 2025-01-13 23:59:10 -05:00
parent 7ff5376d13
commit ab18e15a71
No known key found for this signature in database
8 changed files with 98 additions and 43 deletions

View file

@ -1,6 +1,6 @@
import {
encodeBase32LowerCaseNoPadding,
encodeHexLowerCase,
encodeHexLowerCase
} from "@oslojs/encoding";
import { sha256 } from "@oslojs/crypto/sha2";
import { Session, sessions, User, users } from "@server/db/schema";
@ -9,8 +9,10 @@ import { eq } from "drizzle-orm";
import config from "@server/lib/config";
import type { RandomReader } from "@oslojs/crypto/random";
import { generateRandomString } from "@oslojs/crypto/random";
import logger from "@server/logger";
export const SESSION_COOKIE_NAME = config.getRawConfig().server.session_cookie_name;
export const SESSION_COOKIE_NAME =
config.getRawConfig().server.session_cookie_name;
export const SESSION_COOKIE_EXPIRES = 1000 * 60 * 60 * 24 * 30;
export const SECURE_COOKIES = config.getRawConfig().server.secure_cookies;
export const COOKIE_DOMAIN = "." + config.getBaseDomain();
@ -24,25 +26,25 @@ export function generateSessionToken(): string {
export async function createSession(
token: string,
userId: string,
userId: string
): Promise<Session> {
const sessionId = encodeHexLowerCase(
sha256(new TextEncoder().encode(token)),
sha256(new TextEncoder().encode(token))
);
const session: Session = {
sessionId: sessionId,
userId,
expiresAt: new Date(Date.now() + SESSION_COOKIE_EXPIRES).getTime(),
expiresAt: new Date(Date.now() + SESSION_COOKIE_EXPIRES).getTime()
};
await db.insert(sessions).values(session);
return session;
}
export async function validateSessionToken(
token: string,
token: string
): Promise<SessionValidationResult> {
const sessionId = encodeHexLowerCase(
sha256(new TextEncoder().encode(token)),
sha256(new TextEncoder().encode(token))
);
const result = await db
.select({ user: users, session: sessions })
@ -61,12 +63,12 @@ export async function validateSessionToken(
}
if (Date.now() >= session.expiresAt - SESSION_COOKIE_EXPIRES / 2) {
session.expiresAt = new Date(
Date.now() + SESSION_COOKIE_EXPIRES,
Date.now() + SESSION_COOKIE_EXPIRES
).getTime();
await db
.update(sessions)
.set({
expiresAt: session.expiresAt,
expiresAt: session.expiresAt
})
.where(eq(sessions.sessionId, session.sessionId));
}
@ -81,26 +83,38 @@ export async function invalidateAllSessions(userId: string): Promise<void> {
await db.delete(sessions).where(eq(sessions.userId, userId));
}
export function serializeSessionCookie(token: string): string {
if (SECURE_COOKIES) {
return `${SESSION_COOKIE_NAME}=${token}; HttpOnly; SameSite=Strict; Max-Age=${SESSION_COOKIE_EXPIRES}; Path=/; Secure; Domain=${COOKIE_DOMAIN}`;
export function serializeSessionCookie(
token: string,
isSecure: boolean
): string {
if (isSecure) {
logger.debug("Setting cookie for secure origin");
if (SECURE_COOKIES) {
return `${SESSION_COOKIE_NAME}=${token}; HttpOnly; SameSite=Strict; Max-Age=${SESSION_COOKIE_EXPIRES}; Path=/; Secure; Domain=${COOKIE_DOMAIN}`;
} else {
return `${SESSION_COOKIE_NAME}=${token}; HttpOnly; SameSite=Strict; Max-Age=${SESSION_COOKIE_EXPIRES}; Path=/; Domain=${COOKIE_DOMAIN}`;
}
} else {
return `${SESSION_COOKIE_NAME}=${token}; HttpOnly; SameSite=Strict; Max-Age=${SESSION_COOKIE_EXPIRES}; Path=/; Domain=${COOKIE_DOMAIN}`;
return `${SESSION_COOKIE_NAME}=${token}; HttpOnly; SameSite=Lax; Max-Age=${SESSION_COOKIE_EXPIRES}; Path=/;`;
}
}
export function createBlankSessionTokenCookie(): string {
if (SECURE_COOKIES) {
return `${SESSION_COOKIE_NAME}=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/; Secure; Domain=${COOKIE_DOMAIN}`;
export function createBlankSessionTokenCookie(isSecure: boolean): string {
if (isSecure) {
if (SECURE_COOKIES) {
return `${SESSION_COOKIE_NAME}=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/; Secure; Domain=${COOKIE_DOMAIN}`;
} else {
return `${SESSION_COOKIE_NAME}=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/; Domain=${COOKIE_DOMAIN}`;
}
} else {
return `${SESSION_COOKIE_NAME}=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/; Domain=${COOKIE_DOMAIN}`;
return `${SESSION_COOKIE_NAME}=; HttpOnly; SameSite=Lax; Max-Age=0; Path=/;`;
}
}
const random: RandomReader = {
read(bytes: Uint8Array): void {
crypto.getRandomValues(bytes);
},
}
};
export function generateId(length: number): string {