2.9 KiB
2.9 KiB
| title | aliases | tags | sources | created | updated | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Authentication — JWT Strategy |
|
|
|
2026-05-15 | 2026-05-15 |
Overview
Payload supports JWT-based authentication alongside wiki/payloadcms/authentication-cookies. Tokens are returned from login, logout, refresh, and me operations.
Using the Authorization Header
Pass the JWT via Authorization header for stateless/API clients:
// 1. Login to get token
const { token } = await fetch('http://localhost:3000/api/users/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'dev@payloadcms.com', password: 'password' }),
}).then(r => r.json())
// 2. Authenticate subsequent requests
const response = await fetch('http://localhost:3000/api/posts', {
headers: { Authorization: `JWT ${token}` },
})
- Format:
Authorization: JWT <token>(notBearer) - Alternative to cookie — useful for mobile apps, external services, scripts
Accessing the Logged-In User
Within wiki/payloadcms/local-api and hooks, use req.user:
access: {
read: ({ req }) => req.user?.role === 'admin',
}
Removing Token from Responses
If you don't want the JWT returned in API responses (e.g., cookie-only flows):
export const Users: CollectionConfig = {
slug: 'users',
auth: {
removeTokenFromResponses: true,
},
}
External JWT Validation
When validating Payload-issued JWTs in external services, you must replicate Payload's secret processing — it doesn't use your raw PAYLOAD_SECRET:
import crypto from 'node:crypto'
// Payload's actual signing secret:
const secret = crypto
.createHash('sha256')
.update(process.env.PAYLOAD_SECRET)
.digest('hex')
.slice(0, 32)
- Payload SHA-256 hashes the env secret, then takes the first 32 hex characters
- Use this derived value in your external verifier (e.g.,
jsonwebtoken.verify(token, secret)) - Gotcha: using the raw
PAYLOAD_SECRETin an external verifier will fail silently
Key Takeaways
- JWT header format is
Authorization: JWT <token>— notBearer req.useris available in all access control functions and hooksremoveTokenFromResponses: truehides the token from API responses without disabling JWT auth- External validation requires deriving the signing secret via SHA-256 hash + first 32 chars
- Cookie and JWT auth can coexist — each request uses whichever is present
Related
- wiki/payloadcms/authentication-cookies — alternative auth method
- wiki/payloadcms/authentication-api-keys — non-expiring key auth for integrations
- wiki/payloadcms/authentication-custom-strategies — replace/extend built-in auth
- wiki/payloadcms/rest-api — all auth endpoints (
/login,/me,/refresh)