64 lines
1.9 KiB
TypeScript
64 lines
1.9 KiB
TypeScript
/**
|
|
* Types the payloads of session and password reset tokens, and guards them.
|
|
* `lib/jwt.ts` signs the tokens and runs the guards when it verifies one.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
import { isRole, type Role } from "../../shared/user.ts";
|
|
|
|
/**
|
|
* Signed into a session token by `createJWT`, and returned by `authenticate`
|
|
* to the auth middleware as `ctx.state.user`. By then `role` is the user's live
|
|
* role, while `username` is still the one at issue time.
|
|
*/
|
|
export interface AuthPayload {
|
|
userId: string;
|
|
username: string;
|
|
role: Role;
|
|
/** Seconds since the epoch. */
|
|
exp: number;
|
|
/** Seconds since the epoch, compared with `users.tokens_valid_after`. */
|
|
iat?: number;
|
|
}
|
|
|
|
/**
|
|
* Checks whether `obj` is an {@link AuthPayload}. A media or reset token's
|
|
* payload, which has a `purpose`, never is.
|
|
*/
|
|
export function isAuthPayload(obj: unknown): obj is AuthPayload {
|
|
return !!obj &&
|
|
typeof obj === "object" &&
|
|
// A media or reset token must not pass for a session token.
|
|
!("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";
|
|
}
|
|
|
|
/**
|
|
* Signed into a reset link's token by `createPasswordResetToken`, and returned
|
|
* by `verifyPasswordResetToken` to `resetPassword`.
|
|
*/
|
|
export interface PasswordResetPayload {
|
|
purpose: "password-reset";
|
|
userId: string;
|
|
/** Seconds since the epoch. */
|
|
exp: number;
|
|
}
|
|
|
|
/**
|
|
* Checks whether `obj` is a {@link PasswordResetPayload}. It doesn't check
|
|
* `exp`, which `jwtVerify` has already enforced.
|
|
*/
|
|
export function isPasswordResetPayload(
|
|
obj: unknown,
|
|
): obj is PasswordResetPayload {
|
|
return !!obj && typeof obj === "object" &&
|
|
"purpose" in obj &&
|
|
(obj as Record<string, unknown>).purpose === "password-reset" &&
|
|
"userId" in obj &&
|
|
typeof (obj as Record<string, unknown>).userId === "string";
|
|
}
|