Auth & Session
Built-in per-namespace user account management for the end-users of your application. REGISTER, LOGIN, LOGOUT, SESSION, REFRESH, REVOKE, CONFIRM, COMPARE — no external auth service required.
Architecture note: These verbs manage accounts for your end-users — the people who sign up to the app you build with OQL. They are entirely separate from your OQL API credentials, which you supply in the auth object of each API request. OQL manages the storage internally; you never write SQL for this.
| Verb | Description | Returns |
REGISTER "username" WITH "password" | Create a user account | UID (string) or null if username already exists |
REGISTER "username" WITH "password" AS "email" | Create with email | UID or null |
LOGIN "username" WITH "password" | Authenticate — returns a session token | Token (string) or null on failure |
SESSION ?token | Validate a token — returns the user object or null | {id, username} or null |
LOGOUT ?token | Invalidate a specific session token | Boolean |
REFRESH ?token | Renew a session token — returns a new token | New token or null |
REVOKE "username" | Invalidate all sessions for a user | Number of sessions revoked |
CONFIRM "username" | Mark a user account as confirmed (e.g. after email verification) | Boolean |
COMPARE "a" WITH "b" | Constant-time string comparison — safe for comparing tokens and secrets | Boolean |
REGISTER
REGISTER "alice" WITH "pass1234" SET ?uid
AFTER IF ?uid IS NULL
OPEN NEST
STATUS 409
AFTER EMIT "Username already taken"
CLOSE NEST
ELSE OPEN NEST EMIT "User created: " & ?uid CLOSE NEST
Try it ›
(* With email *)
REGISTER "bob" WITH "securepass" AS "bob@example.com" SET ?uid
AFTER EMIT ?uid
LOGIN
LOGIN "alice" WITH "pass1234" SET ?token
AFTER IF ?token IS NULL
OPEN NEST
STATUS 401
AFTER EMIT "Invalid credentials"
CLOSE NEST
ELSE OPEN NEST COOKIE "session" AS ?token WITH "/" CLOSE NEST
AFTER REDIRECT "/dashboard" AS "302"
Try it ›
SESSION
Validates a session token and returns the user object or null. Use in every protected route.
SESSION !COOKIE(session) SET ?user
AFTER IF ?user IS NULL
OPEN NEST
REDIRECT "/login" AS "302"
AFTER EXIT ALL
CLOSE NEST
ELSE OPEN NEST EMIT "Welcome, " & ?user(username) CLOSE NEST
Try it ›
Handling auth errors with CATCH ERROR
LOGIN and REGISTER throw an error on failure (wrong credentials, duplicate username, etc.) and also return null. You can handle this two ways:
Pattern 1 — CATCH ERROR (recommended): captures the error message string into a variable. The chain continues normally after CATCH ERROR regardless of whether an error occurred.
LOGIN "alice" WITH "wrongpass" SET ?tok
CATCH ERROR SET ?err
AFTER IF ?err IS NOT NULL OPEN NEST
STATUS 401
AFTER EMIT ?err
CLOSE NEST ELSE OPEN NEST
COOKIE "session" AS ?tok(token) WITH "/"
AFTER EMIT "Welcome"
CLOSE NEST
Pattern 2 — null check: simpler but loses the error message.
LOGIN "alice" WITH "pass1234" SET ?tok
AFTER IF ?tok IS NULL OPEN NEST
STATUS 401
AFTER EMIT "Invalid credentials"
CLOSE NEST ELSE OPEN NEST
COOKIE "session" AS ?tok(token) WITH "/"
CLOSE NEST
Note: LOGIN returns {token, user_id} on success — access the token with ?tok(token). REGISTER returns {id, username} on success.
LOGOUT
LOGOUT !COOKIE(session) SET ?ok
AFTER COOKIE DELETE "session"
AFTER REDIRECT "/login" AS "302"
REFRESH
Renews a session token. The old token is invalidated.
REFRESH !COOKIE(session) SET ?new_token
AFTER IF ?new_token IS NOT NULL
OPEN NEST
COOKIE "session" AS ?new_token WITH "/"
CLOSE NEST
REVOKE — invalidate all sessions
REVOKE "alice" SET ?count
AFTER EMIT "Revoked " & ?count & " sessions"
CONFIRM — mark account as verified
(* After verifying an email token — mark the account confirmed *)
CONFIRM ?username SET ?ok
AFTER EMIT ?ok
COMPARE — constant-time token check
Always use COMPARE instead of IS IDENTICAL TO when comparing secrets. It prevents timing attacks.
COMPARE ?submitted_token WITH ?expected_token SET ?valid
AFTER IF ?valid IS EQUAL TO true
OPEN NEST EMIT "accepted" CLOSE NEST
ELSE OPEN NEST STATUS 401 CLOSE NEST
Complete registration + login flow (Site Mode)
(* POST /api/register *)
PARSE JSON !REQUEST(body) SET ?data
AFTER REGISTER ?data(username) WITH ?data(password) AS ?data(email) SET ?uid
AFTER IF ?uid IS NULL
OPEN NEST
STATUS 409
AFTER HEADER "Content-Type" AS "application/json"
AFTER EMIT `{"error":"Username already registered"}`
CLOSE NEST
ELSE OPEN NEST LOGIN ?data(username) WITH ?data(password) SET ?token CLOSE NEST
AFTER STATUS 201
AFTER HEADER "Content-Type" AS "application/json"
AFTER EMIT `{"token":"` & ?token & `","uid":"` & ?uid & `"}`