ConduitMcp.Client.OAuth.Tokens (ConduitMCP v0.11.0)

Copy Markdown View Source

The tokens the client holds for one {principal, issuer, resource}.

access_token and refresh_token are ConduitMcp.Client.Secrets, so inspect/1, logs and crash reports show #Secret<redacted>; the bearer is exposed only where the Authorization header is built. expires_at is Unix seconds computed locally from expires_in (nil when the server gave no lifetime).

iex> tokens = ConduitMcp.Client.OAuth.Tokens.new(access_token: "at", expires_at: 1_000)
iex> inspect(tokens) =~ "at\""
false
iex> ConduitMcp.Client.OAuth.Tokens.expired?(tokens, 960, 30)
false
iex> ConduitMcp.Client.OAuth.Tokens.expired?(tokens, 970, 30)
true

Summary

Functions

Whether the access token is expired, or expires within skew_seconds, at Unix time now: now + skew_seconds >= expires_at. Tokens without expires_at never expire by time (a 401 still triggers a refresh).

Builds tokens from fields, wrapping :access_token and :refresh_token in ConduitMcp.Client.Secret (values already wrapped are kept).

Types

t()

@type t() :: %ConduitMcp.Client.OAuth.Tokens{
  access_token: ConduitMcp.Client.Secret.t(),
  expires_at: integer() | nil,
  refresh_token: ConduitMcp.Client.Secret.t() | nil,
  scopes: [String.t()],
  token_type: String.t()
}

Functions

expired?(tokens, now, skew_seconds \\ 0)

@spec expired?(t(), integer(), non_neg_integer()) :: boolean()

Whether the access token is expired, or expires within skew_seconds, at Unix time now: now + skew_seconds >= expires_at. Tokens without expires_at never expire by time (a 401 still triggers a refresh).

new(fields)

@spec new(keyword()) :: t()

Builds tokens from fields, wrapping :access_token and :refresh_token in ConduitMcp.Client.Secret (values already wrapped are kept).

Raises ArgumentError when :access_token is missing or a field has the wrong type, and KeyError on an unknown field.