UNPKG

@trifrost/core

Version:

Blazingly fast, runtime-agnostic server framework for modern edge and node environments

67 lines (66 loc) 3.05 kB
import { Sym_TriFrostDescription, Sym_TriFrostFingerPrint, Sym_TriFrostName } from '../../types/constants'; import { Sym_TriFrostMiddlewareAuth } from './types'; /* Specific symbol attached to auth mware to identify them by */ export const Sym_TriFrostMiddlewareSessionCookieAuth = Symbol('TriFrost.Middleware.SessionCookieAuth'); /** * Session Cookie Authentication middleware. * * This middleware retrieves a named cookie from the request, typically holding * a session identifier, and calls the provided validate() function. If valid, * the `$auth` state is set on the context. * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies * * @example * .use(SessionCookieAuth({ * cookie: 'session_id', * validate: (ctx, value) => lookupSession(value) * })) */ export function SessionCookieAuth(opts) { if (typeof opts?.cookie !== 'string' || !opts.cookie.length) throw new Error('TriFrostMiddleware@SessionCookieAuth: A cookie name must be provided'); /* Define secret function */ let secretFn; const secretType = typeof opts.secret?.val; if (secretType === 'function') { secretFn = opts.secret.val; } else if (secretType === 'string' && opts.secret.val.length) { secretFn = () => opts.secret.val; } else { throw new Error('TriFrostMiddleware@SessionCookieAuth: A secret must be provided'); } const algorithm = typeof opts.secret.algorithm === 'string' ? opts.secret.algorithm : 'SHA-256'; const validateFn = typeof opts.validate === 'function' ? opts.validate : null; const mware = async function TriFrostSessionCookieAuth(ctx) { /* Get cookie, if cookie is not found return 401 */ const cookie = ctx.cookies.get(opts.cookie); if (typeof cookie !== 'string' || !cookie.length) return ctx.status(401); /* Get resolved secret */ const secret = secretFn(ctx); if (typeof secret !== 'string' || !secret.length) return ctx.status(401); /* Verify HMAC signature */ const verified = await ctx.cookies.verify(cookie, secret, { algorithm }); if (!verified) return ctx.status(401); /* If no validation function, set state and continue */ if (!validateFn) return ctx.setState({ $auth: { cookie: verified } }); /* Validate, if not valid return 401 */ const result = await validateFn(ctx, verified); if (!result) return ctx.status(401); const authenticated = result === true ? { cookie: verified } : result; return ctx.setState({ $auth: authenticated }); }; /* Add symbols for introspection/use further down the line */ Reflect.set(mware, Sym_TriFrostName, 'TriFrostSessionCookieAuth'); Reflect.set(mware, Sym_TriFrostDescription, 'Session Cookie Authentication middleware'); Reflect.set(mware, Sym_TriFrostMiddlewareAuth, true); Reflect.set(mware, Sym_TriFrostFingerPrint, Sym_TriFrostMiddlewareSessionCookieAuth); return mware; }