Supabase JWT Claims for RLS & Access Control
Supabase JWT Claims - hero image

Introduction — Why Supabase JWT Claims Matter

As soon as you move beyond simple authenticated apps and start building SaaS platforms, teams, or role-based access workflows, understanding how Supabase JWT Claims work becomes essential. JWT claims allow you to store extra identity information — such as organization membership, role level, or tenant ID — inside the user token and use that information to enforce Row Level Security (RLS) rules.

Without JWT claims, RLS logic often becomes:

❌ Hard-coded
❌ Dependent on additional queries
❌ Slower or overly complex
❌ Unscalable for multi-tenant systems

With JWT claims, Supabase can enforce authorization directly inside SQL, making your access model:

✔ Faster
✔ Cleaner
✔ More secure
✔ Easier to scale

This guide walks you step-by-step through how to use JWT claims correctly in Supabase — particularly for RLS.

What Are JWT Claims?

JWT (JSON Web Token) claims are pieces of information stored inside the user’s authentication token. Supabase automatically generates standard JWT values, such as:

ClaimDescription
subThe user ID
emailUser’s email
roleSupabase auth role (not app role)

But the real power comes from custom JWT claims, which allow you to store:

  • Organization ID
  • Team memberships
  • Application roles (admin, viewer, member)
  • Feature flags
  • Subscription or billing status

Supabase exposes JWT claims inside SQL using:

auth.jwt()

Why Use JWT Claims With RLS?

When building secure RLS rules, you often need contextual information beyond just auth.uid().

For example:

  • Is this user an admin or standard user?
  • Which tenant do they belong to?
  • Does the user have write, read-only, or no access?

JWT claims allow you to answer those questions without querying another table.

This makes:

⚡ Queries faster
🔐 Policies clearer
🏗 Scalability easier

Adding Custom Claims

Supabase stores custom claims inside the auth.users metadata object.

Example (Node or client-side):

await supabase.auth.updateUser({
  data: {
    app_role: "admin",
    organization_id: "org_abc123"
  }
});

Once updated, Supabase includes them in the JWT.

Accessing JWT Claims in SQL

select auth.jwt()->>'app_role';
select auth.jwt()->>'organization_id';

Using JWT Claims in RLS Policies

Here’s how to build real-world RLS rules using JWT claims.

1 — Role-Based Access Using JWT Claims

create policy "Admins can read everything"
on users
for select
using (auth.jwt()->>'app_role' = 'admin');

2 — Multi-Tenant Access Using organization_id

create policy "Read only own tenant data"
on tasks
for select
using (
  organization_id = auth.jwt()->>'organization_id'
);

3 — Mixed Rule (Tenant Matching + Role Override)

create policy "Tenant-level RBAC"
on tasks
for select
using (
  organization_id = auth.jwt()->>'organization_id'
  or auth.jwt()->>'app_role' = 'admin'
);

Refreshing JWT Claims (Important)

JWT claims do not update immediately after metadata changes.

Users must:

👉 Log out and log back in
or
👉 Refresh the token programmatically:

await supabase.auth.refreshSession()

Common Mistakes When Implementing JWT Claims

MistakeFix
Forgetting to refresh JWT after updating metadataUse .refreshSession()
Storing large objects in metadataKeep claims lightweight
Using service_role key in clientNever do this
Using JWT claims instead of database referencesClaims should mirror, not replace data

Best Practices for Secure App Architecture

✔ Store only what is required for security
✔ Keep naming consistent (organization_id, role)
✔ Combine claims + RLS patterns for multi-tenant SaaS
✔ Refresh tokens after metadata changes
✔ Test user flows with multiple user types

Summary — JWT Claims Make RLS Powerful and Scalable

Using Supabase JWT Claims gives you the ability to:

  • Secure multi-tenant systems
  • Add role-based access
  • Avoid unnecessary database joins
  • Build fast, secure authorization rules

JWT claims aren’t just a feature — they’re the backbone of scalable RLS design.

Want JWT Claims and RLS Done Automatically?

Instead of writing custom claims, update handlers, and policies manually, PromptXL gives you:

  • Prebuilt JWT claim automation
  • Multi-tenant + role-based policy sets
  • Secure RLS templates
  • Fully working SaaS access architecture

No guessing. | No debugging. | No broken permissions.

🚀 Build fast
🔐 Deploy secure
⚡ Scale without rewriting auth logic

👉 Try PromptXL — secure Supabase apps start here.


Related Blogs:

RLS Policies in Supabase: A Beginner-Friendly Overview