ProtoRune. Atproto. OAuth. SessionManager
(proto_rune v0.5.1)
Copy Markdown
A GenServer that keeps an OAuth session fresh for long-running applications.
The manager is opt-in: the SDK starts no processes on its own, so add it to the host application's supervision tree:
children = [
{Registry, keys: :unique, name: MyApp.OAuthRegistry},
{ProtoRune.Atproto.OAuth.SessionManager,
session: session,
client: client,
store: {ProtoRune.Security.TokenStore.Dets, path: "/var/myapp/tokens.dets"},
key: key,
registry: MyApp.OAuthRegistry}
]It schedules a refresh at 75% of the remaining token lifetime (from the
session's expires_at; a 30 minute lifetime is assumed when the
session carries none), rotates the tokens through
ProtoRune.Atproto.OAuth.refresh/2 and persists each new session
through the configured ProtoRune.Security.TokenStore backend under
the session's DID.
Sessions are always encrypted at rest: the serialized session is
encrypted with ProtoRune.Security.Crypto before it reaches the store,
so TokenStore backends never see plaintext. This is mandatory because
the session's dpop_key is private key material, as sensitive as the
tokens themselves.
When a refresh fails the manager stops with {:refresh_failed, reason}
and lets the supervisor decide the restart policy. logout/1 revokes
the refresh token (best effort: a revocation failure does not block the
logout), deletes the stored session and stops the process.
Hosts that manage their own processes can keep calling
ProtoRune.Atproto.OAuth.refresh/2 and ProtoRune.Atproto.OAuth.revoke/2
directly; the manager only composes them.
Options
:session- Required. TheProtoRune.Atproto.OAuth.Sessionto manage.:client- Required. TheProtoRune.Atproto.OAuth.Clientthe session was issued to.:store- Required. A{module, opts}ProtoRune.Security.TokenStorebackend used to persist each refreshed session under its DID.:key- Required. AProtoRune.Security.Cryptokey used to encrypt every persisted session. Generate one withProtoRune.Security.generate_key/0and keep it outside the token storage (seeProtoRune.Security).:registry- Optional name of aRegistrystarted by the host application. When given, the manager registers itself under the session's DID and can be addressed with{:via, Registry, {registry, did}}. The SDK never starts a Registry itself.:refresh_fraction- Fraction of the remaining token lifetime to wait before refreshing (default0.75). Mainly a testing escape hatch.
Telemetry
The manager emits :telemetry events following the same span
conventions as the bot framework (see the ProtoRune.Bot moduledoc):
[:proto_rune, :oauth, :refresh, :start]/:stop/:exception- wrap each token refresh via:telemetry.span/3. Metadata::did; stop events for failed refreshes also carry:error.[:proto_rune, :oauth, :revoke, :start]/:stop/:exception- wrap the revocation performed bylogout/1. Same metadata conventions as the refresh events.
Summary
Functions
Returns a specification to start this module under a supervisor.
Revokes the session, deletes it from the store and stops the manager
with reason :normal.
Returns the session currently held by server (a pid or, when the
manager was started with :registry, a via tuple).
Starts a session manager. See the moduledoc for the accepted options.
Types
@type server() :: GenServer.server()
A reference to a manager: a pid, a registered name or a via tuple.
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec logout(server()) :: :ok
Revokes the session, deletes it from the store and stops the manager
with reason :normal.
Revocation is best effort: a failure is logged and emitted through telemetry but does not block the logout.
@spec session(server()) :: ProtoRune.Atproto.OAuth.Session.t()
Returns the session currently held by server (a pid or, when the
manager was started with :registry, a via tuple).
@spec start_link(keyword()) :: GenServer.on_start()
Starts a session manager. See the moduledoc for the accepted options.