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