Liking cljdoc? Tell your friends :D

dev.arkaitz.auth-base.ceremony

The ceremony of SPEC §6, in three acts: issue a challenge against an identifier, redeem it at most once, end a subject's access everywhere. The method — magic links by email — is implementation one and not the contract; a password, a passkey or a single-use code would arrive as another implementation of these same three calls.

Two properties of the code below are load-bearing and easy to lose in an innocent refactor:

issue! never asks whether the identifier is known. Not once. That is not an optimisation of the anti-enumeration rule (SPEC §11), it is the whole of it: there is no branch to time, because the question is only asked at redemption, when the answer is already in the hands of whoever holds the secret. A future edit that consults the store here to 'avoid pointless work' reintroduces exactly the defect.

A delivery failure is not an authentication failure (SPEC §8). It cannot reach the caller, because reaching the caller means telling them something about the address; it goes to the operator instead.

The ceremony of SPEC §6, in three acts: issue a challenge against an
identifier, redeem it at most once, end a subject's access everywhere. The
method — magic links by email — is implementation one and not the contract;
a password, a passkey or a single-use code would arrive as another
implementation of these same three calls.

Two properties of the code below are load-bearing and easy to lose in an
innocent refactor:

**`issue!` never asks whether the identifier is known.** Not once. That is
not an optimisation of the anti-enumeration rule (SPEC §11), it is the whole
of it: there is no branch to time, because the question is only asked at
redemption, when the answer is already in the hands of whoever holds the
secret. A future edit that consults the store here to 'avoid pointless work'
reintroduces exactly the defect.

**A delivery failure is not an authentication failure** (SPEC §8). It cannot
reach the caller, because reaching the caller means telling them something
about the address; it goes to the operator instead.
raw docstring

ceremonyclj

(ceremony {:keys [store deliver! link ttl-ms clock bootstrap normalise]
           :as config})

Validates the host's configuration and returns the value the three acts take. Every failure is raised here, at construction, naming the key — a malformed link discovered on the first login is a defect found by a user.

:store an implementation of store/Store (required) :deliver! (fn [identifier link]) — gets it to the human (required) :link {:base-url "https://host" :redeem-path "/entrar"} (required) :ttl-ms how long a challenge lives (default 15 minutes) :clock (fn []) → epoch milliseconds (default the system clock) :bootstrap identifiers that hold no record and may still enter (SPEC §12) :normalise (fn [identifier]) → the canonical form (default trim + lower-case)

Validates the host's configuration and returns the value the three acts
take. Every failure is raised here, at construction, naming the key — a
malformed link discovered on the first login is a defect found by a user.

  :store      an implementation of `store/Store` (required)
  :deliver!   (fn [identifier link]) — gets it to the human (required)
  :link       {:base-url "https://host" :redeem-path "/entrar"} (required)
  :ttl-ms     how long a challenge lives (default 15 minutes)
  :clock      (fn []) → epoch milliseconds (default the system clock)
  :bootstrap  identifiers that hold no record and may still enter (SPEC §12)
  :normalise  (fn [identifier]) → the canonical form (default trim + lower-case)
sourceraw docstring

generationclj

(generation {:keys [store]} subject)

The subject's current revocation generation, to be carried by the session it is about to establish.

The subject's current revocation generation, to be carried by the session
it is about to establish.
sourceraw docstring

issue!clj

(issue! {:keys [store deliver! link ttl-ms clock normalise]} identifier)

Records a challenge for identifier and hands the link to deliver!.

Returns nil. Always, whatever the identifier is, and that is the point: a return value that distinguished a known address from an unknown one would put the enumeration back one layer up, in the handler that reads it.

Records a challenge for `identifier` and hands the link to `deliver!`.

Returns nil. Always, whatever the identifier is, and that is the point: a
return value that distinguished a known address from an unknown one would
put the enumeration back one layer up, in the handler that reads it.
sourceraw docstring

redeem!clj

(redeem! {:keys [store clock] :as ceremony} token)

Spends token and returns the subject it attests, or nil.

The challenge is consumed before it is judged: an expired token is spent by the attempt that found it expired, so there is no second look at it.

Spends `token` and returns the subject it attests, or nil.

The challenge is consumed before it is judged: an expired token is spent by
the attempt that found it expired, so there is no second look at it.
sourceraw docstring

revoke!clj

(revoke! {:keys [store]} subject)

Ends the subject's access everywhere (SPEC §10). Every session of theirs carries the generation it was born with and dies at its next request; there is no enumeration of sessions to do, and none is possible over Ring's store protocol, which is why revocation lives on the subject.

Ends the subject's access everywhere (SPEC §10). Every session of theirs
carries the generation it was born with and dies at its next request; there
is no enumeration of sessions to do, and none is possible over Ring's store
protocol, which is why revocation lives on the subject.
sourceraw docstring

subject-ofclj

(subject-of {:keys [store bootstrap normalise]} identifier)

The subject behind an identifier: the store's record, or — only when there is none — a bootstrap identity (SPEC §12). The absence of a record is the signal, not the emptiness of the table, which works once for the first administrator and never again. No row is created either way.

A bootstrap subject carries its identifier and says what it is, so that an audit trail has something to name when there is no local identity at all.

The subject behind an identifier: the store's record, or — **only when there
is none** — a bootstrap identity (SPEC §12). The absence of a record is the
signal, not the emptiness of the table, which works once for the first
administrator and never again. No row is created either way.

A bootstrap subject carries its identifier and says what it is, so that an
audit trail has something to name when there is no local identity at all.
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