$session / $token Variables
$session / $token Variables
Level 8 — Authentication, Permissions & Security Built-in variables containing connection session details (
$session) and JWT token claims ($token), enabling advanced security policies, multi-tenant isolation, and audit logging.
1. Prerequisites
$authVariable — The user record variable.- JWT Token-Based Auth — JSON Web Token structure and claims.
2. Term Category
Authentication & Permissions (token session context variables): - System Variables / Security
3. Explanation
(1) Design Motivation — "Why did we design this?"
While $auth represents the database record of the logged-in user, security policies often depend on connection metadata (e.g. client IP address, origin header, connection protocol) or JWT token claims issued by external identity providers (Auth0, Clerk, Firebase).
SurrealDB provides two specialized system variables:
$session: Contains connection metadata provided by the network transport layer:$session.id: Unique connection session ID.$session.ip: Client IP address.$session.origin: HTTP Origin header.$session.ns: Active Namespace.$session.db: Active Database.
$token: Contains all claims decoded from the incoming JWT token:$token.sub: Subject (User ID).$token.iss: Token Issuer.$token.exp: Expiration timestamp.$token.custom_claim: Any custom payload fields included in the JWT.
(2) Reality Metaphor
Imagine a visitor checking into a secure corporate building:
$auth: The visitor's verified employee profile in the company database.$session: The security camera log recording which physical door they entered through, what time they arrived, and their entry IP/location.$token: The temporary paper pass printed at the front desk, stamped with an expiration time ($token.exp) and authorized floor clearance numbers ($token.floors).
(3) Code Examples
Short Snippet
-- Using $token claims and $session metadata in permissions
DEFINE TABLE audit_log PERMISSIONS
FOR create WHERE $session.ip != NONE AND $token.iss = 'https://auth0.com/';
Fuller Example
-- 1. Audit trail logging using $session and $token
DEFINE EVENT log_write ON TABLE document WHEN $event = 'UPDATE' THEN {
CREATE audit_trail SET
doc_id = $after.id,
user_id = $auth.id,
user_ip = $session.ip,
jwt_issuer = $token.iss,
timestamp = time::now();
};
-- 2. Restricting write access based on custom JWT claim ($token.role)
DEFINE TABLE config SCHEMAFULL
PERMISSIONS
FOR select FULL
FOR update WHERE $token.role = 'admin' AND $session.origin = 'https://app.company.com';
4. Common Mistakes & Pitfalls
Mistake 1: Relying on $token Claims when Using TYPE RECORD without Custom Token Payload
The mistake: Accessing $token.custom_field when using standard SurrealDB TYPE RECORD auth without defining custom JWT token payloads.
Why it's wrong: Standard SurrealDB record auth tokens contain default claims (ID, NS, DB, AC, exp). Custom fields won't exist on $token unless injected via custom JWT signing or external auth providers (TYPE JWT).
Incorrect:
-- Using standard RECORD auth, but expecting $token.department to exist
DEFINE TABLE document PERMISSIONS FOR select WHERE department = $token.department;
Fix:
-- Use $auth.department when using RECORD auth, or $token.department when using external JWT auth
DEFINE TABLE document PERMISSIONS FOR select WHERE department = $auth.department;
Mistake 2: Expecting $token Variables to Be Available in Un-Authenticated Root Connections
The mistake: Referencing $token.exp or $token.id in root administrator queries.
Why it's wrong: $token is populated ONLY during authenticated JWT or RECORD access scope sessions. In unauthenticated root sessions, $token is NONE.
Incorrect:
-- Executed as Root admin:
SELECT * FROM user WHERE id = $token.id; // ❌ $token is NONE!
Fix:
SELECT * FROM user WHERE id = $auth.id; // Record scope authenticated queries
Mistake 3: Confusing $auth (Authenticated Record Object) with $token (JWT Claim Object)
The mistake: Expecting $token to contain table fields that were not embedded in the JWT payload claims.
Why it's wrong: $auth is the full database user record object. $token contains claims decoded directly from the JWT header/payload.
Incorrect:
-- Expecting un-encoded field in $token
SELECT * FROM article WHERE author_name = $token.name; // ❌ Field may not be in token claims!
Fix:
SELECT * FROM article WHERE author = $auth.id; // $auth fetches active record state
5. Practice Exercises
Exercise 1: Session Variables Context Inspection
Scenario:
Inspect all active session variables ($session, $token, $auth) inside an active database query.
Requirements:
- Select
$session.ns,$session.db,$token.sub,$auth.id.
Answer
Implementation
SELECT
$session.ns AS active_ns,
$session.db AS active_db,
$session.id AS session_connection_id,
$token.sub AS token_subject,
$auth.id AS user_id;
Technical Explanation
$sessionholds connection metadata (namespace, database, client IP, connection ID).$tokenholds decoded JWT claims from the client's auth header.$authholds the authenticated user record document.
Exercise 2: Client IP Auditing with $session.origin
Scenario:
Record the client's IP address ($session.origin) inside an audit log record when a sensitive mutation occurs.
Requirements:
- Create
audit_logsettingclient_ip = $session.origin.
Answer
Implementation
CREATE audit_log SET
action = "sensitive_export",
user = $auth.id,
client_ip = $session.origin,
timestamp = time::now();
Technical Explanation
$session.origincaptures incoming client IP addresses or origin domains automatically.- Provides security auditing metrics without requiring backend API header parsing.
- Records connection context at mutation execution time.
Exercise 3: Distinguishing $auth vs $token
Scenario:
Explain the architectural difference between $auth (database user record) and $token (raw JWT payload).
Requirements:
- Contrast
$authrecord properties with$tokenclaim properties.
Answer
Implementation
$auth: Represents the full live database record (e.g. user:alice document with up-to-date fields).
$token: Represents static JSON Web Token claims passed by the client header (e.g. sub, exp, iss).
Technical Explanation
$authfetches live record data from storage during query execution.$tokenreads pre-decoded JWT claim values directly from the request context.- Use
$authfor live record checks; use$tokenfor fast claim inspections.
6. Related Terms
$authVariable — The authenticated record user object.- JWT Token-Based Auth — JWT validation and claims parsing.
DEFINE ACCESS ... TYPE JWT(External Auth Providers) — External auth provider setup.$auth.idvs$auth.*(Accessing Auth Record Fields) — Related concept:$auth.idvs$auth.*(Accessing Auth Record Fields).
7. Key Takeaways
$sessionprovides transport-layer metadata ($session.ip,$session.origin,$session.ns,$session.db).$tokenprovides decoded JWT payload claims ($token.sub,$token.iss,$token.exp).- Essential for audit logging, geo/IP restrictions, and integrating external OAuth provider tokens.