<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/jwt-claims-are-hints-not-the-authorization-policy-qadv7569c" -->

---
title: JWT claims are hints, not the authorization policy
description: JWT claims like role or tenant are signed snapshots taken at token issuance, not a live authorization decision. Because access tokens remain valid for 30-60...
canonical: https://daily.dev/posts/jwt-claims-are-hints-not-the-authorization-policy-qadv7569c
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: JWT claims are hints, not the authorization policy | daily.dev
og:description: JWT claims like role or tenant are signed snapshots taken at token issuance, not a live authorization decision. Because access tokens remain valid for 30-60...
og:url: https://daily.dev/posts/jwt-claims-are-hints-not-the-authorization-policy-qadv7569c
og:image: https://api.daily.dev/og/posts/Qadv7569c.png
og:image:alt: JWT claims are hints, not the authorization policy
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# JWT claims are hints, not the authorization policy

**[Auth By Example](https://daily.dev/sources/7eadcwhmohx0bchehapmt)** · [@authbyexample](https://daily.dev/authbyexample) · 2 min read · 0 upvotes · 0 comments

## Summary

JWT claims like role or tenant are signed snapshots taken at token issuance, not a live authorization decision. Because access tokens remain valid for 30-60 minutes, a demoted admin or revoked group membership can keep passing checks if handlers trust claim values directly. The recommended pattern separates authentication (verifying signature, issuer, audience, expiry) from authorization (checking current roles/attributes/relationships against a live policy store), embedding authz data in tokens only with short TTLs and aggressive invalidation via denylists, version claims, or session revocation. A suggested test: demote a user and call a privileged endpoint with their still-valid token to see if access is wrongly granted until expiry.

## Content

A JWT that says `"role": "admin"` feels authoritative. It isn't. It's a signed snapshot of what someone claimed (or what an IdP asserted) at issue time. The policy that decides access lives elsewhere — and it can change while that token is still valid.

Common failure mode: the API trusts claim values as the decision. Admin flipped in the IdP, group membership revoked, tenant suspended — but the access token still carries the old claims for 30–60 minutes. Every handler that does `if (claims.role === "admin")` keeps granting.

Treat claims as inputs to a decision, not the decision:

1. Authenticate the token (signature, issuer, audience, expiry). That answers "who is this?"

2. Authorize with current policy against the resource: roles/attributes/relationships looked up now, not frozen in the JWT.

3. If you must embed authorization data in the token for latency, keep TTLs short and invalidate aggressively on privilege drop (denylist, version claim, or session revocation).

4. Never invent roles client-side. A claim only matters if your authz layer still agrees after a fresh lookup.

Quick check: demote a user, then call a privileged endpoint with their still-unexpired access token. If it succeeds until expiry, your handlers are doing policy-from-JWT. Fix that before you ship longer-lived tokens.

Identity assertions travel in the token. Authorization decisions should not.

## Similar posts on daily.dev

- [A Stolen Token Is Useless. A Stale One Still Works.](https://daily.dev/posts/a-stolen-token-is-useless-a-stale-one-still-works--1mcdf6whq) · API Evangelist · 1 upvotes · 0 comments
- [JWT Authentication Without the Confusion](https://daily.dev/posts/jwt-authentication-without-the-confusion-tvh5u1id9) · Medium · 1 upvotes · 0 comments
- [Bearer Tokens Explained: Complete Guide to Bearer Token Authentication & Security](https://daily.dev/posts/bearer-tokens-explained-complete-guide-to-bearer-token-authentication-security-f7kgveyal) · Security Boulevard · 0 upvotes · 0 comments
- [JWT-backed authentication can be replayed across organizations](https://daily.dev/posts/jwt-backed-authentication-can-be-replayed-across-organizations-xbeidguk2) · RUBYLAND · 0 upvotes · 0 comments

---

Tags: [#security](https://daily.dev/tags/security), [#authentication](https://daily.dev/tags/authentication), [#authorization](https://daily.dev/tags/authorization), [#jwt](https://daily.dev/tags/jwt)

[View this post on daily.dev](https://daily.dev/posts/jwt-claims-are-hints-not-the-authorization-policy-qadv7569c)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"DiscussionForumPosting","mainEntityOfPage":"https://daily.dev/posts/jwt-claims-are-hints-not-the-authorization-policy-qadv7569c","headline":"JWT claims are hints, not the authorization policy","text":"JWT claims like role or tenant are signed snapshots taken at token issuance, not a live authorization decision. Because access tokens remain valid for 30-60 minutes, a demoted admin or revoked group membership can keep passing checks if handlers trust claim values directly. The recommended pattern separates authentication (verifying signature, issuer, audience, expiry) from authorization (checking current roles/attributes/relationships against a live policy store), embedding authz data in tokens only with short TTLs and aggressive invalidation via denylists, version claims, or session revocation. A suggested test: demote a user and call a privileged endpoint with their still-valid token to see if access is wrongly granted until expiry.","url":"https://daily.dev/posts/jwt-claims-are-hints-not-the-authorization-policy-qadv7569c","datePublished":"2026-09-29T08:13:35.396Z","dateModified":"2026-09-29T08:13:56.002Z","author":{"@type":"Person","name":"Auth By Example","url":"https://daily.dev/authbyexample","image":"https://media.daily.dev/image/upload/s--Fgz7IgGQ--/f_auto/v1789653205/avatars/avatar_7EADCwHmOHX0bChEhAPmt?_a=BAMAMicg0","interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"EndorseAction"},"userInteractionCount":40}},"interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"isPartOf":{"@type":"WebPage","url":"https://daily.dev/sources/7eadcwhmohx0bchehapmt","name":"Auth By Example"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Auth By Example","item":"https://daily.dev/sources/7eadcwhmohx0bchehapmt"},{"@type":"ListItem","position":3,"name":"JWT claims are hints, not the authorization policy"}]}
```

