/** * @file Authentication middleware for validating JWT tokens. * @copyright nhcarrigan * @license Naomi's Public License * @author Naomi Carrigan */ import { verifyToken } from "../services/jwt.js"; import { logger } from "../services/logger.js"; import type { HonoEnvironment } from "../types/hono.js"; import type { MiddlewareHandler } from "hono"; /** * Validates the Authorization Bearer token on each request and attaches the discordId to context. * @param context - The Hono context object. * @param next - The next middleware handler. * @returns A JSON error response if authentication fails, otherwise calls next. */ export const authMiddleware: MiddlewareHandler = async( context, next, ) => { const authorization = context.req.header("Authorization"); if (authorization?.startsWith("Bearer ") !== true) { return context.json( { error: "Missing or invalid Authorization header" }, 401, ); } const token = authorization.slice(7); try { const payload = verifyToken(token); context.set("discordId", payload.discordId); } catch (error) { const isExpiredToken = error instanceof Error && error.message === "Token has expired"; if (!isExpiredToken) { void logger.error( "auth_middleware", error instanceof Error ? error : new Error(String(error)), ); } return context.json({ error: "Invalid or expired token" }, 401); } // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression -- Need the consistent return! return await next(); };