Liking cljdoc? Tell your friends :D

wagoe.platform.core.csrf

Pure CSRF token functions — synchronizer token bound to a session.

The token is a signed double-submit value:

token = base64url(nonce) "." base64url(HMAC-SHA256(secret, nonce || binding))

The binding is the value the token is tied to: the user's session token for authenticated requests, or a per-request pre-session cookie value for the login form (which has no session yet). A token is only valid when presented together with the same binding it was signed against, which is what defeats CSRF: an attacker can forge a cross-site request but cannot read the victim's binding to produce a matching token.

Functional Core: these functions are pure and deterministic. The CSPRNG nonce and the secret are produced in the shell and passed in as arguments — nothing here performs I/O or reads ambient state.

Safety parity with ring-anti-forgery: validation uses buddy's mac/verify, which performs a constant-time comparison of the recomputed HMAC, so token checks do not leak timing information.

Enforcement is opt-in at the interceptor level (default off); see wagoe.platform.shell.http.interceptors/http-csrf-protection. Emit the token with hidden-field (server forms) or hx-headers (HTMX elements), or via the

<meta name="csrf-token"> tag + the ui-style init.js htmx:configRequest listener.

Pure CSRF token functions — synchronizer token bound to a session.

The token is a signed double-submit value:

    token = base64url(nonce) "." base64url(HMAC-SHA256(secret, nonce || binding))

The `binding` is the value the token is tied to: the user's session token for
authenticated requests, or a per-request pre-session cookie value for the login
form (which has no session yet). A token is only valid when presented together
with the same binding it was signed against, which is what defeats CSRF: an
attacker can forge a cross-site request but cannot read the victim's binding to
produce a matching token.

Functional Core: these functions are pure and deterministic. The CSPRNG nonce
and the secret are produced in the shell and passed in as arguments — nothing
here performs I/O or reads ambient state.

Safety parity with ring-anti-forgery: validation uses buddy's `mac/verify`,
which performs a constant-time comparison of the recomputed HMAC, so token
checks do not leak timing information.

Enforcement is opt-in at the interceptor level (default off); see
`wagoe.platform.shell.http.interceptors/http-csrf-protection`. Emit the token
with `hidden-field` (server forms) or `hx-headers` (HTMX elements), or via the
<meta name="csrf-token"> tag + the ui-style init.js htmx:configRequest listener.
raw docstring

*token*clj

The CSRF token for the request currently being handled, or nil. The HTTP interceptor binds this around handler execution (where Hiccup is rendered to a string), so page layouts and form helpers can emit the token without threading it through every handler and component. Mirrors ring-anti-forgery's anti-forgery-token.

The CSRF token for the request currently being handled, or nil. The HTTP
interceptor binds this around handler execution (where Hiccup is rendered to a
string), so page layouts and form helpers can emit the token without threading
it through every handler and component. Mirrors ring-anti-forgery's
*anti-forgery-token*.
sourceraw docstring

current-tokenclj

(current-token)

The CSRF token bound for the current request, or nil outside a request.

The CSRF token bound for the current request, or nil outside a request.
sourceraw docstring

extract-tokenclj

(extract-token request)

Pull the submitted CSRF token from a Ring request, checking, in order:

  1. form param __anti-forgery-token (string or keyword key)
  2. multipart param __anti-forgery-token (file-upload forms)
  3. header x-csrf-token Returns the token String or nil. Pure map access — no I/O.
Pull the submitted CSRF token from a Ring request, checking, in order:
  1. form param      __anti-forgery-token  (string or keyword key)
  2. multipart param __anti-forgery-token  (file-upload forms)
  3. header          x-csrf-token
Returns the token String or nil. Pure map access — no I/O.
sourceraw docstring

field-nameclj

Hidden form-field / form-param name carrying the CSRF token. Mirrors the ring-anti-forgery convention so existing tooling and test helpers interoperate.

Hidden form-field / form-param name carrying the CSRF token. Mirrors the
ring-anti-forgery convention so existing tooling and test helpers interoperate.
sourceraw docstring

generate-tokenclj

(generate-token secret binding nonce-bytes)

Build a CSRF token bound to binding, signed with secret.

Args: secret - signing key (String or bytes); supplied by the shell from config binding - value the token is tied to (session token, or login cookie nonce); may be nil for a pre-session token nonce-bytes - random bytes from a CSPRNG; supplied by the shell

Returns the token String base64url(nonce).base64url(mac).

Build a CSRF token bound to `binding`, signed with `secret`.

Args:
  secret      - signing key (String or bytes); supplied by the shell from config
  binding     - value the token is tied to (session token, or login cookie nonce);
                may be nil for a pre-session token
  nonce-bytes - random bytes from a CSPRNG; supplied by the shell

Returns the token String `base64url(nonce).base64url(mac)`.
sourceraw docstring

header-nameclj

Request header carrying the CSRF token for HTMX / fetch requests.

Request header carrying the CSRF token for HTMX / fetch requests.
sourceraw docstring

hidden-fieldclj

(hidden-field)
(hidden-field token)

Hiccup hidden input embedding the CSRF token in a plain (non-HTMX) form. HTMX requests instead pick up the token from the <meta> tag via the global htmx:configRequest listener, so they do not need this field.

The 0-arity reads the token bound for the current request (token); the 1-arity takes an explicit token. Returns nil when the token is nil, so callers can splice the result into a form unconditionally.

Hiccup hidden input embedding the CSRF token in a plain (non-HTMX) form.
HTMX requests instead pick up the token from the <meta> tag via the global
htmx:configRequest listener, so they do not need this field.

The 0-arity reads the token bound for the current request (*token*); the
1-arity takes an explicit token. Returns nil when the token is nil, so callers
can splice the result into a form unconditionally.
sourceraw docstring

hx-headersclj

(hx-headers)
(hx-headers token)

HTMX attribute fragment carrying the CSRF token, for elements that should send it without relying on the global <meta>/init.js listener. Merge into an element's attribute map (e.g. on <body>) so all inherited hx-* requests include the header: [:body (merge attrs (hx-headers)) ...].

The 0-arity reads the token bound for the current request (token); the 1-arity takes an explicit token. Returns nil when the token is nil, so callers can merge the result unconditionally. The header key uses header-name ("x-csrf-token"); Ring lowercases inbound header names, so the interceptor's extract-token reads it consistently.

HTMX attribute fragment carrying the CSRF token, for elements that should send
it without relying on the global <meta>/init.js listener. Merge into an
element's attribute map (e.g. on <body>) so all inherited hx-* requests include
the header: [:body (merge attrs (hx-headers)) ...].

The 0-arity reads the token bound for the current request (*token*); the 1-arity
takes an explicit token. Returns nil when the token is nil, so callers can merge
the result unconditionally. The header key uses `header-name` ("x-csrf-token");
Ring lowercases inbound header names, so the interceptor's `extract-token` reads
it consistently.
sourceraw docstring

valid-token?clj

(valid-token? secret binding submitted)

True when submitted is a well-formed token whose MAC matches the one recomputed from its nonce and the supplied binding under secret.

Returns false (never throws) for nil, blank, or malformed input, and for any token signed against a different binding or secret. The MAC comparison is constant-time (buddy mac/verify).

True when `submitted` is a well-formed token whose MAC matches the one
recomputed from its nonce and the supplied `binding` under `secret`.

Returns false (never throws) for nil, blank, or malformed input, and for any
token signed against a different binding or secret. The MAC comparison is
constant-time (buddy `mac/verify`).
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close