Some checks failed
Build and Publish Docker Image / build-and-push (push) Failing after 20s
29 lines
1.2 KiB
TypeScript
29 lines
1.2 KiB
TypeScript
import type { Context } from "@oak/oak";
|
|
import { verifyJWT } from "./jwt.ts";
|
|
import { APIErrorCode, APIException } from "../model/interfaces.ts";
|
|
|
|
/**
|
|
* Extracts the userId from an optional Bearer token.
|
|
*
|
|
* Distinguishes *missing* credentials from *invalid* ones:
|
|
* - No `Authorization: Bearer …` header (or a placeholder value such as the
|
|
* `Bearer undefined` that the client emits when logged out) → anonymous (null).
|
|
* - A real token that fails verification (expired / bad signature) → throws 401,
|
|
* so a stale client session surfaces as an auth error it can react to, instead
|
|
* of being silently downgraded to anonymous (which yields a misleading 404 on
|
|
* private resources).
|
|
*/
|
|
export async function parseOptionalAuth(ctx: Context): Promise<string | null> {
|
|
const authHeader = ctx.request.headers.get("Authorization");
|
|
if (!authHeader?.startsWith("Bearer ")) return null;
|
|
|
|
const token = authHeader.substring(7).trim();
|
|
if (!token || token === "undefined" || token === "null") return null;
|
|
|
|
const payload = await verifyJWT(token);
|
|
if (!payload) {
|
|
throw new APIException(APIErrorCode.UNAUTHORIZED, 401, "Invalid token");
|
|
}
|
|
return payload.userId;
|
|
}
|