---
title: "Authentication — Token Data (saveToJWT)"
aliases: [token-data, jwt-token-data, saveToJWT]
tags: [payloadcms, authentication, jwt, access-control]
sources: [raw/authentication__token-data.md]
created: 2026-05-15
updated: 2026-05-15
---

## Overview

Payload lets you embed any field value into the Cookie/JWT so it's available on every request via `req.user` — without an extra DB lookup.

## Defining Token Data

Add `saveToJWT: true` to any field in an auth collection:

```ts
export const Users: CollectionConfig = {
  slug: 'users',
  auth: true,
  fields: [
    {
      saveToJWT: true,       // stored in JWT at key "role"
      type: 'select',
      name: 'role',
      options: ['super-admin', 'user'],
    },
  ],
}
```

### Group / Tab Fields

| Config | Result |
|--------|--------|
| `saveToJWT: true` on the **group** | Entire group object stored under its `name` key |
| `saveToJWT: true` on a **field inside** a group | That field hoisted to **top level** of JWT |
| `saveToJWT: false` on a field inside a `saveToJWT: true` group | Field **omitted** from JWT |

### Custom Key

Pass a string instead of `true` to store the value under a different key:

```ts
{ saveToJWT: 'userRole', name: 'role', type: 'select', ... }
// → req.user.userRole
```

## Using Token Data

`req.user` is populated automatically on every authenticated request:

```ts
export const Invoices: CollectionConfig = {
  slug: 'invoices',
  access: {
    read: ({ req, data }) => {
      if (!req?.user) return false
      if (req.user?.role === 'super-admin') return true
      return data.owner === req.user.id
    },
  },
  // ...
}
```

Useful in [[wiki/payloadcms/authentication-overview|Hooks]] and [[wiki/payloadcms/authentication-operations|Access Control]] wherever you need role/tenant/group info without hitting the DB.

## Key Takeaways

- `saveToJWT: true` on a field → value baked into every JWT/cookie issued at login
- Group-level `saveToJWT: true` → stores the whole group object; field-level inside a group → hoists to top level
- `saveToJWT: false` on a child field overrides parent group's `saveToJWT: true`
- `saveToJWT: "customKey"` stores data under that key instead of the field `name`
- Access via `req.user.<fieldName>` in any hook or access-control function — no extra DB query needed
- Re-login required after changing `saveToJWT` fields; existing tokens won't have the new data

## Related

- [[wiki/payloadcms/authentication-overview|Authentication Overview]] — enable auth, all config options
- [[wiki/payloadcms/authentication-jwt|JWT Strategy]] — `Authorization` header flow, token validation
- [[wiki/payloadcms/authentication-custom-strategies|Custom Auth Strategies]] — replace built-in auth entirely
- [[wiki/payloadcms/authentication-operations|Auth Operations]] — login, refresh, me endpoints

## Sources

- `raw/authentication__token-data.md`
- https://payloadcms.com/docs/authentication/token-data
