/** * The payloads of the tokens the server signs, and their guards. * * @module */ import { isRole, type Role } from "../../shared/user.ts"; /** What a session token carries. */ export interface AuthPayload { /** The user's id. */ userId: string; /** The user's name when the token was issued. */ username: string; /** * The user's role; the live one replaces it once the token is authenticated. */ role: Role; /** When the token expires, in seconds since the epoch. */ exp: number; /** When the token was issued, in seconds since the epoch. */ iat?: number; } /** * Checks whether `obj` is an {@link AuthPayload}, and not a purpose-scoped * token's payload. */ export function isAuthPayload(obj: unknown): obj is AuthPayload { return !!obj && typeof obj === "object" && // Purpose-scoped tokens (password reset, media) are never session tokens. !("purpose" in obj) && "userId" in obj && typeof obj.userId === "string" && "username" in obj && typeof obj.username === "string" && "role" in obj && isRole(obj.role) && "exp" in obj && typeof obj.exp === "number"; } /** What a password reset token carries. */ export interface PasswordResetPayload { /** The token's purpose, which makes it a reset token. */ purpose: "password-reset"; /** The id of the user whose password it resets. */ userId: string; /** When the token expires, in seconds since the epoch. */ exp: number; } /** Checks whether `obj` is a {@link PasswordResetPayload}. */ export function isPasswordResetPayload( obj: unknown, ): obj is PasswordResetPayload { return !!obj && typeof obj === "object" && "purpose" in obj && (obj as Record).purpose === "password-reset" && "userId" in obj && typeof (obj as Record).userId === "string"; }