SuperPi.Auth (super_pi v0.1.0)

Copy Markdown View Source

Bearer-token authentication and conversation ownership for the Gateway and RPC server.

Tokens

Configure tokens with config :super_pi, gateway_tokens: [...] or the SUPER_PI_GATEWAY_TOKEN environment variable (comma separated). An entry is either a token string or a {name, token} pair. A named entry makes the principal readable in logs and ownership records. An unnamed token gets the principal token:<hash prefix>. The older single :gateway_token key still works.

With no tokens configured the endpoints are open, which is safe only on a loopback address. SuperPi.Gateway.Server refuses to start on another address without a token. Open endpoints use the principal "anonymous".

Ownership

The first principal to create a conversation owns it (pi.owner document). Another principal gets :not_found for it, the same answer as for a conversation that does not exist, so an id does not reveal that a conversation exists. A conversation with no owner (created by the CLI, or before this check existed) belongs to "anonymous", so it is reachable only when authentication is off.

Summary

Functions

Principal used when authentication is off.

Checks a presented token. Returns {:ok, principal} or :error. With no tokens configured, any call (including a missing token) is {:ok, "anonymous"}.

True when principal may use the conversation.

Extracts the token from an Authorization: Bearer ... header value.

Records principal as the owner of conversation_id.

Owner of a conversation ("anonymous" when none is recorded).

True when at least one token is configured.

Returns %{token => principal} from config and environment.

Functions

anonymous()

Principal used when authentication is off.

authenticate(presented)

@spec authenticate(String.t() | nil) :: {:ok, String.t()} | :error

Checks a presented token. Returns {:ok, principal} or :error. With no tokens configured, any call (including a missing token) is {:ok, "anonymous"}.

authorized?(conversation_id, principal)

True when principal may use the conversation.

bearer_token(arg1)

Extracts the token from an Authorization: Bearer ... header value.

claim!(conversation_id, principal)

Records principal as the owner of conversation_id.

owner(conversation_id)

Owner of a conversation ("anonymous" when none is recorded).

required?()

True when at least one token is configured.

tokens()

@spec tokens() :: %{required(String.t()) => String.t()}

Returns %{token => principal} from config and environment.