Cookie Strategy

Payload offers the ability to Authenticate via HTTP-only cookies. These can be read from the responses of login, logout, refresh, and me auth operations.

Automatic browser inclusion

Modern browsers automatically include http-only cookies when making requests directly to URLs—meaning that if you are running your API on https://example.com, and you have logged in and visit https://example.com/test-page, your browser will automatically include the Payload authentication cookie for you.

HTTP Authentication

However, if you use fetch or similar APIs to retrieve Payload resources from its REST or GraphQL API, you must specify to include credentials (cookies).

Fetch example, including credentials:

1
const response = await fetch('http://localhost:3000/api/pages', {
2
credentials: 'include',
3
})
4
5
const pages = await response.json()

For more about including cookies in requests from your app to your Payload API, read the MDN docs.

CSRF Attacks

CSRF (cross-site request forgery) attacks are common and dangerous. By using an HTTP-only cookie, Payload removes many XSS vulnerabilities, however, CSRF attacks can still be possible.

For example, let's say you have a popular app https://payload-finances.com that allows users to manage finances, send and receive money. As Payload is using HTTP-only cookies, that means that browsers automatically will include cookies when sending requests to your domain - no matter what page created the request.

So, if a user of https://payload-finances.com is logged in and is browsing around on the internet, they might stumble onto a page with malicious intent. Let's look at an example:

1
// malicious-intent.com
2
// makes an authenticated request as on your behalf
3
4
const maliciousRequest = await fetch(`https://payload-finances.com/api/me`, {
5
credentials: 'include'
6
}).then(res => await res.json())

In this scenario, if your cookie was still valid, malicious-intent.com would be able to make requests like the one above on your behalf. This is a CSRF attack.

CSRF Prevention

Define domains that your trust and are willing to accept Payload HTTP-only cookie based requests from. Use the csrf option on the base Payload Config to do this:

1
// payload.config.ts
2
3
import { buildConfig } from 'payload'
4
5
const config = buildConfig({
6
serverURL: 'https://my-payload-instance.com',
7
csrf: [
8
// whitelist of domains to allow cookie auth from
9
'https://your-frontend-app.com',
10
'https://your-other-frontend-app.com',
11
// `config.serverURL` is added by default if defined
12
],
13
collections: [
14
// collections here
15
],
16
})
17
18
export default config
Next

JWT Strategy