payloadcms-ext-jwt-validation
v1.0.0
Published
Validate PayloadCMS-issued JWTs locally using the processed secret — no CMS callback needed.
Downloads
171
Maintainers
Readme
payloadcms-ext-jwt-validation
Validate PayloadCMS-issued JWTs locally — no CMS callback needed.
PayloadCMS signs JWTs using a processed secret (SHA-256(PAYLOAD_SECRET) → hex → first 32 chars). This library verifies tokens using that processed secret via jose, keeping your services decoupled from the CMS.
Installation
npm install payloadcms-ext-jwt-validationHow It Works (Two-Step Flow)
Step 1: PayloadCMS side — generate the processed secret
import { processSecret } from "payloadcms-ext-jwt-validation";
const processedSecret = processSecret(process.env.PAYLOAD_SECRET!);
console.log(processedSecret);
// → e.g. "a1b2c3d4e5f6..." (32-char hex string)
// Copy this value into the target service's .envStep 2: Target service — verify JWTs
import { validatePayloadRequest } from "payloadcms-ext-jwt-validation";
// PROCESSED_SECRET is the output from Step 1, stored in .env
const user = await validatePayloadRequest(req.headers, req.cookies, {
secret: process.env.PROCESSED_SECRET!,
});
console.log(user);
// { id: 'abc123', collection: 'users', roles: ['admin'], sid: 'sess-xyz' }API
validatePayloadRequest(headers, cookies?, options) → Promise<CurrentUser>
All-in-one convenience: extract → verify → map.
| Param | Type | Description |
| --------- | -------------------------------------------------- | ------------------------- |
| headers | Record<string, string \| string[] \| undefined> | HTTP request headers |
| cookies | Record<string, string \| undefined> \| undefined | Parsed cookies (optional) |
| options | PayloadJwtOptions | See below |
PayloadJwtOptions:
| Field | Type | Default | Description |
| ------------- | --------- | ----------------- | ---------------------------------------------------- |
| secret | string | — | The processed secret (output of processSecret) |
| allowCookie | boolean | false | Also look for token in cookies |
| cookieName | string | 'payload-token' | Cookie name to read |
processSecret(rawSecret) → string
Derive the 32-char processed secret from the raw PAYLOAD_SECRET. Run this once on the PayloadCMS side, then copy the output to your target service's env.
extractToken(headers, cookies?, options?) → string | null
Extract the JWT string from Authorization: Bearer|JWT header, or from a cookie.
verifyPayloadJwt(token, processedSecret) → Promise<PayloadJwtPayload>
Verify a JWT string using the processed secret. Throws on invalid/expired tokens.
mapPayloadUser(payload) → CurrentUser
Map a raw JWT payload to a normalized CurrentUser object.
Error Handling
import {
JwtMissingError,
JwtExpiredError,
JwtValidationError,
} from "payloadcms-ext-jwt-validation";
try {
const user = await validatePayloadRequest(headers, cookies, options);
} catch (err) {
if (err instanceof JwtMissingError) {
// 401 — no token found
} else if (err instanceof JwtExpiredError) {
// 401 — token expired
} else if (err instanceof JwtValidationError) {
// 401 — invalid signature or malformed token
}
}Types
interface CurrentUser {
id: string;
collection: string;
roles: string[];
sid?: string;
email?: string;
}
interface PayloadJwtPayload {
collection: string;
id: string;
sid?: string;
email?: string;
roles?: string[];
[key: string]: unknown; // saveToJWT custom fields
}License
MIT
