Authentication and user management against Supabase Auth.
Supports password, OAuth, OTP, SSO, ID-token, Web3 and anonymous sign-in,
user retrieval and sign-up, the full session/identity lifecycle
(verify-otp, refresh-session, update-user, resend,
reset-password-for-email, exchange-code-for-session, reauthenticate,
get-claims, identity linking), user OAuth grant management
(list-oauth-grants, revoke-oauth-grant), OAuth 2.1 server consent
(get-authorization-details, approve-authorization,
deny-authorization) and server observability (get-server-health,
get-server-settings).
See supabase.auth.admin for the service-role admin API.
(require '[supabase.core.client :as client]
'[supabase.auth :as auth])
(def c (client/make-client "https://abc.supabase.co" "anon-key"))
(auth/sign-up c {:email "user@example.com" :password "secure-password"})
(auth/sign-in-with-password c {:email "user@example.com" :password "secure-password"})
Each function returns {:status :body :headers} on success or an anomaly
map on failure. On ClojureScript every function that issues an HTTP call
returns a js/Promise of that value instead (fetch is async-only).
See https://supabase.com/docs/reference/javascript/auth-api
Authentication and user management against Supabase Auth.
Supports password, OAuth, OTP, SSO, ID-token, Web3 and anonymous sign-in,
user retrieval and sign-up, the full session/identity lifecycle
(`verify-otp`, `refresh-session`, `update-user`, `resend`,
`reset-password-for-email`, `exchange-code-for-session`, `reauthenticate`,
`get-claims`, identity linking), user OAuth grant management
(`list-oauth-grants`, `revoke-oauth-grant`), OAuth 2.1 server consent
(`get-authorization-details`, `approve-authorization`,
`deny-authorization`) and server observability (`get-server-health`,
`get-server-settings`).
See `supabase.auth.admin` for the service-role admin API.
## Example
(require '[supabase.core.client :as client]
'[supabase.auth :as auth])
(def c (client/make-client "https://abc.supabase.co" "anon-key"))
(auth/sign-up c {:email "user@example.com" :password "secure-password"})
(auth/sign-in-with-password c {:email "user@example.com" :password "secure-password"})
Each function returns `{:status :body :headers}` on success or an anomaly
map on failure. On ClojureScript every function that issues an HTTP call
returns a `js/Promise` of that value instead (fetch is async-only).
See https://supabase.com/docs/reference/javascript/auth-apiServer-side admin operations against the Supabase Auth API.
Every function here requires a client configured with the project's
service-role key (not the anon key) as its access token — these
endpoints bypass Row-Level Security and must never be exposed to a browser.
(require '[supabase.core.client :as client]
'[supabase.auth.admin :as admin])
(def c (client/make-client "https://abc.supabase.co" "service-role-key"))
(admin/create-user c {:email "user@example.com" :password "secret"
:email-confirm true})
(admin/list-users c {:page 1 :per-page 50})
Each function returns {:status :body :headers} on success or an anomaly
map on failure. See https://supabase.com/docs/reference/javascript/auth-admin-api
Server-side admin operations against the Supabase Auth API.
Every function here requires a `client` configured with the project's
**service-role** key (not the anon key) as its access token — these
endpoints bypass Row-Level Security and must never be exposed to a browser.
## Example
(require '[supabase.core.client :as client]
'[supabase.auth.admin :as admin])
(def c (client/make-client "https://abc.supabase.co" "service-role-key"))
(admin/create-user c {:email "user@example.com" :password "secret"
:email-confirm true})
(admin/list-users c {:page 1 :per-page 50})
Each function returns `{:status :body :headers}` on success or an anomaly
map on failure. See https://supabase.com/docs/reference/javascript/auth-admin-apiCustom OAuth2 / OIDC provider administration against the Supabase Auth API.
Registers and manages identity providers beyond the built-in social login list, e.g. a private OIDC issuer or a partner's OAuth2 server.
Like the rest of supabase.auth.admin, every function requires a client
configured with the project's service-role key.
(require '[supabase.core.client :as client]
'[supabase.auth.admin.custom-providers :as providers])
(def c (client/make-client "https://abc.supabase.co" "service-role-key"))
(providers/create-provider c {:provider-type "oidc"
:identifier "acme"
:name "Acme SSO"
:client-id "client-id"
:client-secret "client-secret"
:discovery-url "https://sso.acme.com/.well-known/openid-configuration"})
(providers/list-providers c)
Each function returns {:status :body :headers} on success or an anomaly
map on failure.
Custom OAuth2 / OIDC provider administration against the Supabase Auth API.
Registers and manages identity providers beyond the built-in social login
list, e.g. a private OIDC issuer or a partner's OAuth2 server.
Like the rest of `supabase.auth.admin`, every function requires a client
configured with the project's **service-role** key.
## Example
(require '[supabase.core.client :as client]
'[supabase.auth.admin.custom-providers :as providers])
(def c (client/make-client "https://abc.supabase.co" "service-role-key"))
(providers/create-provider c {:provider-type "oidc"
:identifier "acme"
:name "Acme SSO"
:client-id "client-id"
:client-secret "client-secret"
:discovery-url "https://sso.acme.com/.well-known/openid-configuration"})
(providers/list-providers c)
Each function returns `{:status :body :headers}` on success or an anomaly
map on failure.OAuth 2.1 client administration against the Supabase Auth API.
Manages the OAuth clients registered on the project (dynamic client registration), used when the Supabase project acts as an OAuth authorization server.
Like the rest of supabase.auth.admin, every function requires a client
configured with the project's service-role key.
(require '[supabase.core.client :as client]
'[supabase.auth.admin.oauth :as oauth])
(def c (client/make-client "https://abc.supabase.co" "service-role-key"))
(oauth/create-client c {:client-name "my-app"
:redirect-uris ["https://app.example.com/cb"]})
(oauth/list-clients c)
Each function returns {:status :body :headers} on success or an anomaly
map on failure.
OAuth 2.1 client administration against the Supabase Auth API.
Manages the OAuth clients registered on the project (dynamic client
registration), used when the Supabase project acts as an OAuth
authorization server.
Like the rest of `supabase.auth.admin`, every function requires a client
configured with the project's **service-role** key.
## Example
(require '[supabase.core.client :as client]
'[supabase.auth.admin.oauth :as oauth])
(def c (client/make-client "https://abc.supabase.co" "service-role-key"))
(oauth/create-client c {:client-name "my-app"
:redirect-uris ["https://app.example.com/cb"]})
(oauth/list-clients c)
Each function returns `{:status :body :headers}` on success or an anomaly
map on failure.Passkey administration against the Supabase Auth API.
Manages the passkeys registered by users, used when the Supabase project has the passkeys (WebAuthn) authentication method enabled.
Like the rest of supabase.auth.admin, every function requires a client
configured with the project's service-role key.
(require '[supabase.core.client :as client]
'[supabase.auth.admin.passkey :as passkey])
(def c (client/make-client "https://abc.supabase.co" "service-role-key"))
(passkey/list-passkeys c "<user-id>")
(passkey/delete-passkey c "<user-id>" "<passkey-id>")
Each function returns {:status :body :headers} on success or an anomaly
map on failure.
Passkey administration against the Supabase Auth API.
Manages the passkeys registered by users, used when the Supabase project
has the passkeys (WebAuthn) authentication method enabled.
Like the rest of `supabase.auth.admin`, every function requires a client
configured with the project's **service-role** key.
## Example
(require '[supabase.core.client :as client]
'[supabase.auth.admin.passkey :as passkey])
(def c (client/make-client "https://abc.supabase.co" "service-role-key"))
(passkey/list-passkeys c "<user-id>")
(passkey/delete-passkey c "<user-id>" "<passkey-id>")
Each function returns `{:status :body :headers}` on success or an anomaly
map on failure.Auth-specific HTTP error mapping.
Installed on every Auth request via with-auth-errors. Parity with the
auth-js handleError logic:
msg,
message, error_description or error field) instead of a generic
status phrase.weak_password (as :code or
:error_code), or the legacy :weak_password body shape - are tagged
:supabase/code :weak-password and carry the failing rules under
:auth/weak-password-reasons.Auth-specific HTTP error mapping.
Installed on every Auth request via [[with-auth-errors]]. Parity with the
auth-js `handleError` logic:
* 5xx responses keep the server's own message (the body's `msg`,
`message`, `error_description` or `error` field) instead of a generic
status phrase.
* Weak-password rejections - error code `weak_password` (as `:code` or
`:error_code`), or the legacy `:weak_password` body shape - are tagged
`:supabase/code :weak-password` and carry the failing rules under
`:auth/weak-password-reasons`.Local JWT decoding and asymmetric signature verification for Supabase Auth.
Supabase issues JWTs signed with either a symmetric secret (HS256, the
legacy default — not verifiable client-side) or an asymmetric key
(RS256 / ES256). For asymmetric algorithms the public keys are
published at <auth-url>/.well-known/jwks.json; on the JVM this
namespace fetches and caches that JWKS and verifies signatures using the
JDK's built-in crypto, with no third-party dependency.
ClojureScript gets decode only: signature verification stays on the
JVM (or server-side via supabase.auth/get-user), since fetching and
caching JWKS is an async operation on that platform.
Callers should use supabase.auth/get-claims rather than these helpers
directly.
Local JWT decoding and asymmetric signature verification for Supabase Auth. Supabase issues JWTs signed with either a symmetric secret (`HS256`, the legacy default — not verifiable client-side) or an asymmetric key (`RS256` / `ES256`). For asymmetric algorithms the public keys are published at `<auth-url>/.well-known/jwks.json`; on the JVM this namespace fetches and caches that JWKS and verifies signatures using the JDK's built-in crypto, with no third-party dependency. ClojureScript gets [[decode]] only: signature verification stays on the JVM (or server-side via `supabase.auth/get-user`), since fetching and caching JWKS is an async operation on that platform. Callers should use [[supabase.auth/get-claims]] rather than these helpers directly.
Multi-factor authentication against Supabase Auth.
Supports TOTP (authenticator apps), phone (SMS / WhatsApp) and WebAuthn
factors. Every function acts on behalf of the signed-in user identified
by access-token — the JWT from an active session.
The usual TOTP flow:
(require '[supabase.auth.mfa :as mfa])
;; 1. enroll — body carries the QR code / secret to show the user
(mfa/enroll client token {:factor-type "totp" :friendly-name "authenticator"})
;; 2. user scans the QR and types the 6-digit code
(mfa/challenge-and-verify client token factor-id "123456")
Phone and WebAuthn factors need the explicit challenge + verify
round-trip since the response arrives out of band.
Recovery codes (experimental server-side) give users a fallback when their usual factor is unavailable:
(mfa/generate-recovery-codes client token) ;; show codes once
(mfa/get-recovery-codes-status client token) ;; remaining count
(mfa/verify-recovery-code client token {:code "K4M9-X7QP-2AB8-HT3Z"})
(mfa/regenerate-recovery-codes client token) ;; replaces the set
(mfa/unenroll-recovery-codes client token) ;; remove the factor
Each function returns {:status :body :headers} on success or an anomaly
map on failure. On ClojureScript every function returns a js/Promise of
that value instead (fetch is async-only).
See https://supabase.com/docs/guides/auth/auth-mfa
Multi-factor authentication against Supabase Auth.
Supports TOTP (authenticator apps), phone (SMS / WhatsApp) and WebAuthn
factors. Every function acts on behalf of the signed-in user identified
by `access-token` — the JWT from an active session.
The usual TOTP flow:
(require '[supabase.auth.mfa :as mfa])
;; 1. enroll — body carries the QR code / secret to show the user
(mfa/enroll client token {:factor-type "totp" :friendly-name "authenticator"})
;; 2. user scans the QR and types the 6-digit code
(mfa/challenge-and-verify client token factor-id "123456")
Phone and WebAuthn factors need the explicit `challenge` + `verify`
round-trip since the response arrives out of band.
Recovery codes (experimental server-side) give users a fallback when
their usual factor is unavailable:
(mfa/generate-recovery-codes client token) ;; show codes once
(mfa/get-recovery-codes-status client token) ;; remaining count
(mfa/verify-recovery-code client token {:code "K4M9-X7QP-2AB8-HT3Z"})
(mfa/regenerate-recovery-codes client token) ;; replaces the set
(mfa/unenroll-recovery-codes client token) ;; remove the factor
Each function returns `{:status :body :headers}` on success or an anomaly
map on failure. On ClojureScript every function returns a `js/Promise` of
that value instead (fetch is async-only).
See https://supabase.com/docs/guides/auth/auth-mfaPasskey (WebAuthn) REST API against Supabase Auth.
This is the low-level, two-step API plus passkey management, acting on
behalf of the signed-in user identified by access-token — the JWT from
an active session. The browser-side WebAuthn ceremony (prompting the user
and marshalling credentials) lives in supabase.auth.webauthn; use it
unless you run the ceremony yourself.
Two-step registration (requires an active session):
(require '[supabase.auth.passkey :as passkey])
;; 1. challenge + credential creation options for the browser
(passkey/start-registration client token)
;; 2. verify the credential the ceremony produced
(passkey/verify-registration client token challenge-id credential)
Two-step authentication (no session yet, so no access token — the client's API key authenticates the request, mirroring auth-js):
(passkey/start-authentication client)
(passkey/verify-authentication client challenge-id credential)
Management:
(passkey/list client token)
(passkey/update client token passkey-id "my laptop")
(passkey/delete client token passkey-id)
Each function returns {:status :body :headers} on success or an anomaly
map on failure. On ClojureScript every function returns a js/Promise of
that value instead (fetch is async-only).
See https://supabase.com/docs/guides/auth/passkeys
Passkey (WebAuthn) REST API against Supabase Auth.
This is the low-level, two-step API plus passkey management, acting on
behalf of the signed-in user identified by `access-token` — the JWT from
an active session. The browser-side WebAuthn ceremony (prompting the user
and marshalling credentials) lives in [[supabase.auth.webauthn]]; use it
unless you run the ceremony yourself.
Two-step registration (requires an active session):
(require '[supabase.auth.passkey :as passkey])
;; 1. challenge + credential creation options for the browser
(passkey/start-registration client token)
;; 2. verify the credential the ceremony produced
(passkey/verify-registration client token challenge-id credential)
Two-step authentication (no session yet, so no access token — the client's
API key authenticates the request, mirroring auth-js):
(passkey/start-authentication client)
(passkey/verify-authentication client challenge-id credential)
Management:
(passkey/list client token)
(passkey/update client token passkey-id "my laptop")
(passkey/delete client token passkey-id)
Each function returns `{:status :body :headers}` on success or an anomaly
map on failure. On ClojureScript every function returns a `js/Promise` of
that value instead (fetch is async-only).
See https://supabase.com/docs/guides/auth/passkeysRing middleware for Supabase Auth JWT verification.
Verifies the bearer token on incoming requests via
supabase.auth/get-claims (local JWKS verification for asymmetric
algorithms, server-side check for HS256) and attaches the verified claims
to the request map. Depends only on the Ring request/response map shape,
not on Ring itself.
(require '[supabase.auth.ring :as auth.ring])
(def app
(-> handler
(auth.ring/wrap-authentication client {:required? true})))
;; downstream handlers read the verified identity:
(defn handler [request]
(let [user-id (get-in request [:supabase/claims :sub])]
...))
Ring middleware for Supabase Auth JWT verification.
Verifies the bearer token on incoming requests via
[[supabase.auth/get-claims]] (local JWKS verification for asymmetric
algorithms, server-side check for HS256) and attaches the verified claims
to the request map. Depends only on the Ring request/response map shape,
not on Ring itself.
## Example
(require '[supabase.auth.ring :as auth.ring])
(def app
(-> handler
(auth.ring/wrap-authentication client {:required? true})))
;; downstream handlers read the verified identity:
(defn handler [request]
(let [user-id (get-in request [:supabase/claims :sub])]
...))Pluggable session persistence for Supabase Auth.
The auth functions are stateless: the caller owns the session map
returned by sign-in / verify-otp / refresh-session. This namespace
provides a small protocol for persisting that session between process
restarts (or, on ClojureScript, page reloads), matching the client's
:auth :persist-session / :storage-key configuration.
Implementations:
atom-session-store — in-memory atom. Both platforms; the
default choice on the JVM.local-storage-session-store — browser localStorage,
ClojureScript only. Keyed by the client's :auth :storage-key.(def store (session-store/atom-session-store))
(session-store/save-session store (:body (auth/sign-in-with-password c creds)))
(session-store/load-session store) ;; => session map or nil
(session-store/clear-session store) ;; sign-out
Pluggable session persistence for Supabase Auth.
The auth functions are stateless: the caller owns the session map
returned by sign-in / `verify-otp` / `refresh-session`. This namespace
provides a small protocol for persisting that session between process
restarts (or, on ClojureScript, page reloads), matching the client's
`:auth :persist-session` / `:storage-key` configuration.
Implementations:
- [[atom-session-store]] — in-memory atom. Both platforms; the
default choice on the JVM.
- `local-storage-session-store` — browser `localStorage`,
ClojureScript only. Keyed by the client's `:auth :storage-key`.
## Example
(def store (session-store/atom-session-store))
(session-store/save-session store (:body (auth/sign-in-with-password c creds)))
(session-store/load-session store) ;; => session map or nil
(session-store/clear-session store) ;; sign-outMalli schemas for Supabase Auth entities and operations.
Used internally to validate API responses and operation inputs. Schemas follow the Supabase Auth API specification: https://supabase.com/docs/reference/javascript/auth-api
Malli schemas for Supabase Auth entities and operations. Used internally to validate API responses and operation inputs. Schemas follow the Supabase Auth API specification: https://supabase.com/docs/reference/javascript/auth-api
WebAuthn ceremony helpers for passkeys.
Three layers, ported from auth-js (lib/base64url.ts, lib/webauthn.ts,
lib/webauthn.dom.ts):
bytes->base64url /
base64url->bytes over vectors of bytes.deserialize-credential-creation-options /
deserialize-credential-request-options turn the server's W3C JSON
options (base64url strings) into the JS objects
navigator.credentials.create/get expect;
serialize-credential-creation-response /
serialize-credential-request-response turn a credential back into
the JSON-ready map the server verifies.register-passkey and sign-in-with-passkey run the full
start -> prompt -> verify round-trip against
supabase.auth.passkey.Unlike auth-js this port always uses the manual JSON marshalling (the
W3C parseCreationOptionsFromJSON / toJSON fast paths are not taken),
so behaviour is identical across browsers. Detailed WebAuthn error
identification (auth-js webauthn.errors.ts) is also out of scope:
ceremony failures become :cognitect.anomalies/incorrect anomalies
carrying the browser error name under :webauthn/error-name.
Every ClojureScript-only function returns an anomaly on the JVM instead: passkeys require ClojureScript and a WebAuthn-capable browser.
TESTING GAP: the WebAuthn ceremony itself (navigator.credentials.create
/ .get) cannot run under node or jsdom. The codec and marshalling are
unit-tested on both platforms (the orchestration wiring against a
hand-rolled fake navigator.credentials); a real WebAuthn ceremony needs
manual verification in a browser against a Supabase project with
passkeys enabled.
WebAuthn ceremony helpers for passkeys.
Three layers, ported from auth-js (`lib/base64url.ts`, `lib/webauthn.ts`,
`lib/webauthn.dom.ts`):
* Base64-URL codec — pure, cross-platform: `bytes->base64url` /
`base64url->bytes` over vectors of bytes.
* DOM <-> JSON marshalling — ClojureScript-only:
`deserialize-credential-creation-options` /
`deserialize-credential-request-options` turn the server's W3C JSON
options (base64url strings) into the JS objects
`navigator.credentials.create`/`get` expect;
`serialize-credential-creation-response` /
`serialize-credential-request-response` turn a credential back into
the JSON-ready map the server verifies.
* High-level ceremony orchestration — ClojureScript-only:
`register-passkey` and `sign-in-with-passkey` run the full
start -> prompt -> verify round-trip against
`supabase.auth.passkey`.
Unlike auth-js this port always uses the manual JSON marshalling (the
W3C `parseCreationOptionsFromJSON` / `toJSON` fast paths are not taken),
so behaviour is identical across browsers. Detailed WebAuthn error
identification (auth-js `webauthn.errors.ts`) is also out of scope:
ceremony failures become `:cognitect.anomalies/incorrect` anomalies
carrying the browser error name under `:webauthn/error-name`.
Every ClojureScript-only function returns an anomaly on the JVM instead:
passkeys require ClojureScript and a WebAuthn-capable browser.
TESTING GAP: the WebAuthn ceremony itself (`navigator.credentials.create`
/ `.get`) cannot run under node or jsdom. The codec and marshalling are
unit-tested on both platforms (the orchestration wiring against a
hand-rolled fake `navigator.credentials`); a real WebAuthn ceremony needs
manual verification in a browser against a Supabase project with
passkeys enabled.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |