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#

1
{
2
"aal": "aal1",
3
"amr": [
4
{
5
"method": "password",
6
"timestamp": 1640991600
7
}
8
],
9
"app_metadata": {
10
"provider": "email",
11
"providers": ["email"]
12
},
13
"aud": "authenticated",
14
"email": "user@example.com",
15
"exp": 1640995200,
16
"iat": 1640991600,
17
"iss": "https://abcdefghijklmnopqrst.supabase.co/auth/v1",
18
"phone": "",
19
"role": "authenticated",
20
"session_id": "123e4567-e89b-12d3-a456-426614174000",
21
"sub": "123e4567-e89b-12d3-a456-426614174000",
22
"user_metadata": {
23
"name": "John Doe"
24
},
25
"is_anonymous": false
26
}

Anonymous user token#

1
{
2
"iss": "supabase",
3
"ref": "abcdefghijklmnopqrst",
4
"role": "anon",
5
"iat": 1640991600,
6
"exp": 1640995200
7
}

Service role token#

1
{
2
"iss": "supabase",
3
"ref": "abcdefghijklmnopqrst",
4
"role": "service_role",
5
"iat": 1640991600,
6
"exp": 1640995200
7
}

Language-Specific considerations#

Rust#

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

1
use serde::{Deserialize, Serialize};
2
3
#[derive(Debug, Deserialize, Serialize)]
4
struct JwtClaims {
5
iss: String,
6
#[serde(rename = "ref")] // Handle reserved keyword
7
project_ref: Option<String>,
8
role: String,
9
iat: i64,
10
exp: i64,
11
// ... other claims
12
}

TypeScript/JavaScript#

1
interface {
2
: string
3
: string | string[]
4
: number
5
: number
6
: string
7
: string
8
: 'aal1' | 'aal2'
9
: string
10
: string
11
: string
12
: boolean
13
?: string
14
?: number
15
?: <string, any>
16
?: <string, any>
17
?: <{
18
: string
19
: number
20
}>
21
?: string // Only in anon/service role tokens
22
}

Python#

1
from typing import Optional, Union, List, Dict, Any
2
from dataclasses import dataclass
3
4
@dataclass
5
class AmrEntry:
6
method: str
7
timestamp: int
8
9
@dataclass
10
class JwtClaims:
11
iss: str
12
aud: Union[str, List[str]]
13
exp: int
14
iat: int
15
sub: str
16
role: str
17
aal: str
18
session_id: str
19
email: str
20
phone: str
21
is_anonymous: bool
22
jti: Optional[str] = None
23
nbf: Optional[int] = None
24
app_metadata: Optional[Dict[str, Any]] = None
25
user_metadata: Optional[Dict[str, Any]] = None
26
amr: Optional[List[AmrEntry]] = None
27
ref: Optional[str] = None # Only in anon/service role tokens

Go#

1
type AmrEntry struct {
2
Method string `json:"method"`
3
Timestamp int64 `json:"timestamp"`
4
}
5
6
type JwtClaims struct {
7
Iss string `json:"iss"`
8
Aud interface{} `json:"aud"` // string or []string
9
Exp int64 `json:"exp"`
10
Iat int64 `json:"iat"`
11
Sub string `json:"sub"`
12
Role string `json:"role"`
13
Aal string `json:"aal"`
14
SessionID string `json:"session_id"`
15
Email string `json:"email"`
16
Phone string `json:"phone"`
17
IsAnonymous bool `json:"is_anonymous"`
18
Jti *string `json:"jti,omitempty"`
19
Nbf *int64 `json:"nbf,omitempty"`
20
AppMetadata map[string]interface{} `json:"app_metadata,omitempty"`
21
UserMetadata map[string]interface{} `json:"user_metadata,omitempty"`
22
Amr []AmrEntry `json:"amr,omitempty"`
23
Ref *string `json:"ref,omitempty"` // Only in anon/service role tokens
24
}

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