Skip to content
Auth

JWT Claims Reference

Complete reference for claims appearing in JWTs created by Supabase Auth

This page provides a comprehensive reference for all JWT claims used in Supabase authentication tokens. This information is essential for server-side JWT validation and serialization, especially when implementing authentication in languages like Rust where field names like ref are reserved keywords.

JWT structure overview#

Supabase JWTs follow the standard JWT structure with three parts:

  • Header: Contains algorithm and key information
  • Payload: Contains the claims (user data and metadata)
  • Signature: Cryptographic signature for verification

The payload contains various claims that provide user identity, authentication level, and authorization information.

Required claims#

These claims are always present in Supabase JWTs and cannot be removed:

FieldTypeDescriptionExample
issstringIssuer - The entity that issued the JWT"https://project-ref.supabase.co/auth/v1"
audstring | string[]Audience - The intended recipient of the JWT"authenticated" or "anon"
expnumberExpiration Time - Unix timestamp when the token expires1640995200
iatnumberIssued At - Unix timestamp when the token was issued1640991600
substringSubject - The user ID (UUID)"123e4567-e89b-12d3-a456-426614174000"
rolestringRole - User's role in the system"authenticated", "anon", "service_role"
aalstringAuthenticator Assurance Level - Authentication strength"aal1", "aal2"
session_idstringSession ID - Unique session identifier"session-uuid"
emailstringEmail - User's email address"user@example.com"
phonestringPhone - User's phone number"+1234567890"
is_anonymousbooleanAnonymous Flag - Whether the user is anonymousfalse

Optional claims#

These claims may be present depending on the authentication context:

FieldTypeDescriptionExample
jtistringJWT ID - Unique identifier for the JWT"jwt-uuid"
nbfnumberNot Before - Unix timestamp before which the token is invalid1640991600
app_metadataobjectApp Metadata - Application-specific user data{"provider": "email"}
user_metadataobjectUser Metadata - User-specific data{"name": "John Doe"}
amrarrayAuthentication Methods Reference - List of authentication methods used[{"method": "password", "timestamp": 1640991600}]

Special claims#

FieldTypeDescriptionExampleContext
refstringProject Reference - Supabase project identifier"abcdefghijklmnopqrst"Anon/Service role tokens only

Field value constraints#

Authenticator assurance level (aal)#

ValueDescription
"aal1"Single-factor authentication (password, OAuth, etc.)
"aal2"Multi-factor authentication (password + TOTP, etc.)

Role values (role)#

ValueDescriptionUse Case
"anon"Anonymous userPublic access with RLS policies
"authenticated"Authenticated userStandard user access
"service_role"Service roleAdmin privileges (server-side only)

Audience values (aud)#

ValueDescription
"authenticated"For authenticated user tokens
"anon"For anonymous user tokens

Authentication methods (amr.method)#

ValueDescription
"oauth"OAuth provider authentication
"password"Email/password authentication
"otp"One-time password
"totp"Time-based one-time password
"recovery"Account recovery
"invite"Invitation-based signup
"sso/saml"SAML single sign-on
"magiclink"Magic link authentication
"email/signup"Email signup
"email_change"Email change
"token_refresh"Token refresh
"anonymous"Anonymous authentication

JWT examples#

Authenticated user token#

{
"aal": "aal1",
"amr": [
{
"method": "password",
"timestamp": 1640991600
}
],
"app_metadata": {
"provider": "email",
"providers": ["email"]
},
"aud": "authenticated",
"email": "user@example.com",
"exp": 1640995200,
"iat": 1640991600,
"iss": "https://abcdefghijklmnopqrst.supabase.co/auth/v1",
"phone": "",
"role": "authenticated",
"session_id": "123e4567-e89b-12d3-a456-426614174000",
"sub": "123e4567-e89b-12d3-a456-426614174000",
"user_metadata": {
"name": "John Doe"
},
"is_anonymous": false
}

Anonymous user token#

{
"iss": "supabase",
"ref": "abcdefghijklmnopqrst",
"role": "anon",
"iat": 1640991600,
"exp": 1640995200
}

Service role token#

{
"iss": "supabase",
"ref": "abcdefghijklmnopqrst",
"role": "service_role",
"iat": 1640991600,
"exp": 1640995200
}

Language-Specific considerations#

Rust#

In Rust, the ref field is a reserved keyword. When deserializing JWTs, you'll need to handle this:

use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]
struct JwtClaims {
iss: String,
#[serde(rename = "ref")] // Handle reserved keyword
project_ref: Option<String>,
role: String,
iat: i64,
exp: i64,
// ... other claims
}

TypeScript/JavaScript#

interface JwtClaims {
iss: string
aud: string | string[]
exp: number
iat: number
sub: string
role: string
aal: 'aal1' | 'aal2'
session_id: string
email: string
phone: string
is_anonymous: boolean
jti?: string
nbf?: number
app_metadata?: Record<string, any>
user_metadata?: Record<string, any>
amr?: Array<{
method: string
timestamp: number
}>
ref?: string // Only in anon/service role tokens
}

Python#

from typing import Optional, Union, List, Dict, Any
from dataclasses import dataclass
@dataclass
class AmrEntry:
method: str
timestamp: int
@dataclass
class JwtClaims:
iss: str
aud: Union[str, List[str]]
exp: int
iat: int
sub: str
role: str
aal: str
session_id: str
email: str
phone: str
is_anonymous: bool
jti: Optional[str] = None
nbf: Optional[int] = None
app_metadata: Optional[Dict[str, Any]] = None
user_metadata: Optional[Dict[str, Any]] = None
amr: Optional[List[AmrEntry]] = None
ref: Optional[str] = None # Only in anon/service role tokens

Go#

type AmrEntry struct {
Method string `json:"method"`
Timestamp int64 `json:"timestamp"`
}
type JwtClaims struct {
Iss string `json:"iss"`
Aud interface{} `json:"aud"` // string or []string
Exp int64 `json:"exp"`
Iat int64 `json:"iat"`
Sub string `json:"sub"`
Role string `json:"role"`
Aal string `json:"aal"`
SessionID string `json:"session_id"`
Email string `json:"email"`
Phone string `json:"phone"`
IsAnonymous bool `json:"is_anonymous"`
Jti *string `json:"jti,omitempty"`
Nbf *int64 `json:"nbf,omitempty"`
AppMetadata map[string]interface{} `json:"app_metadata,omitempty"`
UserMetadata map[string]interface{} `json:"user_metadata,omitempty"`
Amr []AmrEntry `json:"amr,omitempty"`
Ref *string `json:"ref,omitempty"` // Only in anon/service role tokens
}

Validation guidelines#

When implementing JWT validation on your server:

  1. Check Required Fields: Ensure all required claims are present
  2. Validate Types: Verify field types match expected types
  3. Check Expiration: Validate exp timestamp is in the future
  4. Verify Issuer: Ensure iss matches your Supabase project
  5. Check Audience: Validate aud matches expected audience
  6. Handle Reserved Keywords: Use field renaming for languages like Rust

Security considerations#

  • Always validate the JWT signature before trusting any claims
  • Never expose service role tokens to client-side code
  • Validate all claims before trusting the JWT
  • Check token expiration on every request
  • Use HTTPS for all JWT transmission
  • Rotate JWT secrets regularly
  • Implement proper error handling for invalid tokens