What the platform running Managoat.OAuth supplies: everything the grant
state machine needs to know about subjects, tokens and the record it
leaves, and nothing about grants.
subject_allowed?/1— may this subject collect a token right now? Asked bypoll_device_grantbefore the grant is consumed, so a subject the host has suspended (or one whose approval predates a change of state) is refused with{:error, :access_denied}and the grant is left approved and unconsumed. The code exchange does not ask: the consent that issued the code was the host's check.issue_token/3— mint the token for a consumed grant.grantsays which kind and what the library decided about it:%{type: :authorization_code, id: code_id, client_id: "spa", expires_at: %DateTime{}} %{type: :device, id: grant_id, client_id: nil, expires_at: nil}expires_atis the library's token lifetime for that grant (thirty days for a code, none for a device grant); a host honours it. Returns{:ok, %{access_token: raw, token: anything}}:access_tokenis the bearer string the client receives,tokenis whatever the host wants handed back to its own caller (Fountain puts its%ApiKey{}there). Any{:error, _}becomes{:error, :server_error}to the caller. For a code the grant is already consumed when this is called; see theManagoat.OAuthmoduledoc for why.audit/3— a mutation happened.eventis one of:authorized(a code was issued;metahassubject_id,client_id,redirect_uri),:device_approvedand:device_denied(metahassubject_idandgrant_id). The library cannot complete any of these three mutations without calling this, which is what lets a host say its OAuth mutations are audited by construction. Return:ok; a host that wants recording to be best-effort rescues inside.
subject is an opaque binary throughout: the library stores it, hands it
back, and never joins it to anything. opts is the keyword list the
host's own caller passed to the instance function, untouched, so
attribution (an actor, a request IP) travels from the host's web layer to
the host's audit trail without the library reading it.
Summary
Types
@type event() :: :authorized | :device_approved | :device_denied
@type grant() :: %{ type: :authorization_code | :device, id: binary(), client_id: String.t() | nil, expires_at: DateTime.t() | nil }
@type subject() :: binary()