summary refs log tree commit diff
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2026-07-21 15:43:51 +0200
committerRory& <root@rory.gay>2026-07-21 15:43:51 +0200
commit98e50a6d57ebb48fd0b5fec148aa14aeaf95a1dd (patch)
tree9e5696656438a0bac1f022333e3bc862f090db30
parentNixOS: systemd slices (diff)
downloadserver-ts-98e50a6d57ebb48fd0b5fec148aa14aeaf95a1dd.tar.xz
Move authentication enforcement to route middleware, move route middleware file
-rw-r--r--src/api/middlewares/Authentication.ts46
-rw-r--r--src/api/middlewares/Route.ts (renamed from src/api/util/handlers/route.ts)9
-rw-r--r--src/api/middlewares/index.ts1
-rw-r--r--src/api/util/index.ts1
4 files changed, 24 insertions, 33 deletions
diff --git a/src/api/middlewares/Authentication.ts b/src/api/middlewares/Authentication.ts

index a71dfdf1..fe57880a 100644 --- a/src/api/middlewares/Authentication.ts +++ b/src/api/middlewares/Authentication.ts
@@ -20,7 +20,7 @@ import { NextFunction, Request, Response } from "express"; import { HTTPError } from "lambert-server/HTTPError"; import { Session, User } from "@spacebar/database"; import { Random } from "@spacebar/extensions"; -import { checkToken, Rights, UserTokenData } from "@spacebar/util"; +import { checkToken, DiscordApiErrors, Rights, UserTokenData } from "@spacebar/util"; export const NO_AUTHORIZATION_ROUTES = [ // Authentication routes @@ -77,6 +77,7 @@ declare global { session?: Session; rights: Rights; fingerprint?: string; + isAuthenticated: boolean; } } } @@ -96,33 +97,16 @@ export async function Authentication(req: Request, res: Response, next: NextFunc `__sb_sessid=${(req.fingerprint = Random.getString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 32))}; Secure; HttpOnly; SameSite=None; Path=/`, ); - if ( - NO_AUTHORIZATION_ROUTES.some((x) => { - if (typeof x !== "string") { - return x.test(req.method + " " + url); - } + await handleAuthentication(req); - const fullRoute = req.method + " " + url; - - if (req.method === "HEAD") { - const urlPart = x.split(" ").slice(1).join(" "); - if (urlPart.endsWith("/")) { - return url.startsWith(urlPart); - } else { - return url === urlPart; - } - } - - if (x.endsWith("/")) { - return fullRoute.startsWith(x); - } else { - return fullRoute === x; - } - }) - ) - return next(); + return next(); +} - if (!req.headers.authorization) return next(new HTTPError("Missing Authorization Header", 401)); +export async function handleAuthentication(req: Request) { + if (!req.headers.authorization) { + req.isAuthenticated = false; + return; + } try { const { decoded, user, session } = (req.tokenData = await checkToken(req.headers.authorization, { @@ -136,11 +120,9 @@ export async function Authentication(req: Request, res: Response, next: NextFunc req.user = user; req.session = session; req.rights = new Rights(Number(user.rights)); - return next(); - } catch (error) { - if (error instanceof HTTPError) { - return next(error); - } - return next(new HTTPError(error!.toString(), 400)); + req.isAuthenticated = true; + } catch (e) { + req.isAuthenticated = false; + console.error("[Authentication] Token was provided, but was invalid:", e); } } diff --git a/src/api/util/handlers/route.ts b/src/api/middlewares/Route.ts
index c00a959d..69c2b25e 100644 --- a/src/api/util/handlers/route.ts +++ b/src/api/middlewares/Route.ts
@@ -74,6 +74,11 @@ export interface RouteOptions { // event?: EVENT | EVENT[]; // headers?: Record<string, string>; // }; + + /** + * @defaultValue "required" + */ + authentication?: "never" | "optional" | "required"; } export function stripNull(obj: object) { for (const [key, value] of Object.entries(obj)) { @@ -126,7 +131,11 @@ export function route(opts: RouteOptions) { if (!validate) throw new Error(`Body schema ${opts.requestBody} not found`); } + opts.authentication ??= "required"; + return async (req: Request, res: Response, next: NextFunction) => { + if (opts.authentication === "required" && !req.isAuthenticated) throw DiscordApiErrors.UNAUTHORIZED; + if (opts.permission) { const { guild_id, channel_id } = req.params as { [key: string]: string }; req.permission = await getPermission(req.user_id, guild_id, channel_id); diff --git a/src/api/middlewares/index.ts b/src/api/middlewares/index.ts
index a2bb00b3..22651b53 100644 --- a/src/api/middlewares/index.ts +++ b/src/api/middlewares/index.ts
@@ -22,4 +22,5 @@ export * from "./CORS"; export * from "./ErrorHandler"; export * from "./ImageProxy"; export * from "./RateLimit"; +export * from "./Route"; export * from "./Translation"; diff --git a/src/api/util/index.ts b/src/api/util/index.ts
index b57d263a..5fb5a684 100644 --- a/src/api/util/index.ts +++ b/src/api/util/index.ts
@@ -19,7 +19,6 @@ export * from "./utility/ipAddress"; export * from "./handlers/Message"; export * from "./utility/passwordStrength"; -export * from "./handlers/route"; export * from "./handlers/Voice"; export * from "./utility/captcha"; export * from "./utility/EmbedHandlers";