Files
payloadcms/docs/authentication/jwt.mdx
Kwan Jun Wen 0a5b7b0485 docs: clarify JWT token encryption / decryption in configuration docs (#13816)
### What?

This PR adds back clarification that the `secret` configured in Payload
is not used directly to sign JWT tokens, which can cause confusion when
attempting to verify tokens in other services.

### Why?

There was previously an issue (#2441) that explained this unexpected
behavior, and documentation was added to clarify it. However, that
clarification has since been removed from the current docs, which led to
confusion when I attempted to validate the JWT in another service and
received an "invalid signature" error.

### How?

- Included a brief explanation and a cautionary warning to inform
developers of this custom behavior.

Fixes #13814
2025-09-18 13:23:19 -04:00

70 lines
2.2 KiB
Plaintext

---
title: JWT Strategy
label: JWT Strategy
order: 40
desc: Enable JSON Web Token based authentication to interface with Payload.
keywords: authentication, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
---
Payload offers the ability to [Authenticate](./overview) via JSON Web Tokens (JWT). These can be read from the responses of `login`, `logout`, `refresh`, and `me` auth operations.
<Banner type="success">
**Tip:** You can access the logged-in user from within [Access
Control](../access-control/overview) and [Hooks](../hooks/overview) through
the `req.user` argument. [More details](./token-data).
</Banner>
### Identifying Users Via The Authorization Header
In addition to authenticating via an HTTP-only cookie, you can also identify users via the `Authorization` header on an HTTP request.
Example:
```ts
const user = 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((req) => await req.json())
const request = await fetch('http://localhost:3000', {
headers: {
Authorization: `JWT ${user.token}`,
},
})
```
### Omitting The Token
In some cases you may want to prevent the token from being returned from the auth operations. You can do that by setting `removeTokenFromResponses` to `true` like so:
```ts
import type { CollectionConfig } from 'payload'
export const UsersWithoutJWTs: CollectionConfig = {
slug: 'users-without-jwts',
auth: {
removeTokenFromResponses: true, // highlight-line
},
}
```
## External JWT Validation
When validating Payload-generated JWT tokens in external services, use the processed secret rather than your original secret key:
```ts
import crypto from 'node:crypto'
const secret = crypto.createHash('sha256').update(process.env.PAYLOAD_SECRET).digest('hex').slice(0, 32)
```
<Banner type="info">
**Note:** Payload processes your secret using SHA-256 hash and takes the first 32 characters. This processed value is what's used for JWT operations, not your original secret.
</Banner>