apps/docs/content/guides/auth/jwt-fields.mdx
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.
Supabase JWTs follow the standard JWT structure with three parts:
The payload contains various claims that provide user identity, authentication level, and authorization information.
These claims are always present in Supabase JWTs and cannot be removed:
| Field | Type | Description | Example |
|---|---|---|---|
iss | string | Issuer - The entity that issued the JWT | "https://project-ref.supabase.co/auth/v1" |
aud | string | string[] | Audience - The intended recipient of the JWT | "authenticated" or "anon" |
exp | number | Expiration Time - Unix timestamp when the token expires | 1640995200 |
iat | number | Issued At - Unix timestamp when the token was issued | 1640991600 |
sub | string | Subject - The user ID (UUID) | "123e4567-e89b-12d3-a456-426614174000" |
role | string | Role - User's role in the system | "authenticated", "anon", "service_role" |
aal | string | Authenticator Assurance Level - Authentication strength | "aal1", "aal2" |
session_id | string | Session ID - Unique session identifier | "session-uuid" |
email | string | Email - User's email address | "[email protected]" |
phone | string | Phone - User's phone number | "+1234567890" |
is_anonymous | boolean | Anonymous Flag - Whether the user is anonymous | false |
These claims may be present depending on the authentication context:
| Field | Type | Description | Example |
|---|---|---|---|
jti | string | JWT ID - Unique identifier for the JWT | "jwt-uuid" |
nbf | number | Not Before - Unix timestamp before which the token is invalid | 1640991600 |
app_metadata | object | App Metadata - Application-specific user data | {"provider": "email"} |
user_metadata | object | User Metadata - User-specific data | {"name": "John Doe"} |
amr | array | Authentication Methods Reference - List of authentication methods used | [{"method": "password", "timestamp": 1640991600}] |
| Field | Type | Description | Example | Context |
|---|---|---|---|---|
ref | string | Project Reference - Supabase project identifier | "abcdefghijklmnopqrst" | Anon/Service role tokens only |
aal)| Value | Description |
|---|---|
"aal1" | Single-factor authentication (password, OAuth, etc.) |
"aal2" | Multi-factor authentication (password + TOTP, etc.) |
role)| Value | Description | Use Case |
|---|---|---|
"anon" | Anonymous user | Public access with RLS policies |
"authenticated" | Authenticated user | Standard user access |
"service_role" | Service role | Admin privileges (server-side only) |
aud)| Value | Description |
|---|---|
"authenticated" | For authenticated user tokens |
"anon" | For anonymous user tokens |
amr.method)| Value | Description |
|---|---|
"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 |
{
"aal": "aal1",
"amr": [
{
"method": "password",
"timestamp": 1640991600
}
],
"app_metadata": {
"provider": "email",
"providers": ["email"]
},
"aud": "authenticated",
"email": "[email protected]",
"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
}
{
"iss": "supabase",
"ref": "abcdefghijklmnopqrst",
"role": "anon",
"iat": 1640991600,
"exp": 1640995200
}
{
"iss": "supabase",
"ref": "abcdefghijklmnopqrst",
"role": "service_role",
"iat": 1640991600,
"exp": 1640995200
}
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
}
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
}
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
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
}
When implementing JWT validation on your server:
exp timestamp is in the futureiss matches your Supabase projectaud matches expected audience