Skip to content

docs(data-api): explain JWT role claim and anonymous fallback for custom providers - #5555

Draft
bgrenon wants to merge 1 commit into
mainfrom
polly/feedback-lkb16518-dataapi-jwt-role
Draft

docs(data-api): explain JWT role claim and anonymous fallback for custom providers#5555
bgrenon wants to merge 1 commit into
mainfrom
polly/feedback-lkb16518-dataapi-jwt-role

Conversation

@bgrenon

@bgrenon bgrenon commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Doc-only fixes from the docs-drift feedback audit: 3 Data API pages corrected so custom (JWKS) auth providers understand how the database role is chosen. Not auto-merged — awaiting your review.

Why

A custom-JWKS token can be accepted (valid signature) yet still get 42501 permission denied for table X, even though the table is granted to authenticated and SET ROLE authenticated works in the SQL Editor. The cause: the Data API takes the database role from the JWT role claim. Neon Auth stamps role: authenticated, but a custom provider does not unless you configure it to. With no matching role claim, the request runs as the fallback anonymous role, which has schema USAGE but no table grants, so it returns 42501. The docs didn't explain this, and access-control.md implied any valid token becomes authenticated.

Changes

1. access-control.md — the role always comes from the role claim (was: "valid token")

  • Before: "Used for: Requests with a valid JWT token. When a client sends a valid Bearer token, the API switches to the authenticated role."
  • After: "Used for: Tokens that carry "role": "authenticated". ... A valid signature on its own does not grant the authenticated role; the token must actually carry "role": "authenticated"."
  • Also reframes the ## API Roles intro and the "Custom roles" section around the general rule (the role is whatever the claim names; anonymous is the fallback), and fixes the page summary.
  • Why the new text is right: a request carrying role: authenticated returns 200 with rows; the same request with no role claim returns 403 / 42501. The role is selected from the claim, not from token validity.

2. custom-authentication-providers.md — new "Required JWT claims" section

Explains that the token must carry a role claim naming a granted role, that using the default authenticated role requires the provider to issue "role": "authenticated", and that a missing role claim falls back to anonymous (no table access) and returns 42501.

3. troubleshooting.md — new cause under "Permission denied for table" (42501)

Adds the custom-provider / absent-role-claim case and the fix (issue a role claim naming a granted role, or point the Data API's JWT role claim key at your provider's claim).

Files

File Change
content/docs/data-api/access-control.md Role comes from the role claim, not from token validity; fix summary + 3 role subsections
content/docs/data-api/custom-authentication-providers.md Add "Required JWT claims" section
content/docs/data-api/troubleshooting.md Add absent-role-claim cause + fix to the 42501 entry

How to verify

Text-only; no build or runtime behavior is affected. To check the behavior the docs now describe, enable the Data API with a custom (external JWKS) provider and grant SELECT on a table to authenticated, then call the Data API:

  • A Bearer token whose payload includes "role": "authenticated" returns 200 with rows.
  • The same token with no role claim returns 403 with {"code":"42501","message":"permission denied for table ..."} — it ran as anonymous.
  • A token whose role claim names a role that doesn't exist returns 400 with {"code":"22023","message":"role \"...\" does not exist"}.

Verified against live Neon: the three calls above returned 200 (rows), 403/42501, and 400/22023 respectively, with the Data API configured for a custom JWKS provider and default grants to authenticated.

Fixes LKB-16518

Source: neon-docs-drift feedback feed (#lakebase-feed-user-feedback)

…tom providers

The Data API takes the database role from the JWT `role` claim; a token with
no role claim falls back to the `anonymous` role, which has no table grants by
default and returns 42501. Custom (JWKS) providers don't stamp `role:
authenticated` unless configured to, so their tokens hit 42501 even when
`authenticated` is granted. Correct the misleading "valid token -> authenticated"
wording in access-control, add a "Required JWT claims" section to
custom-authentication-providers, and add this cause to the 42501 troubleshooting
entry.

Fixes LKB-16518

Co-authored-by: Isaac
@vercel

vercel Bot commented Aug 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
neon-next Ready Ready Preview Aug 17, 2026 2:16am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant