ExMCP.Authorization.TokenManager (ex_mcp v0.9.0)
View SourceManages OAuth tokens with automatic refresh and expiration tracking.
This GenServer maintains tokens, monitors their expiration, and automatically refreshes them before they expire, following MCP authorization best practices.
Features
- Automatic token refresh before expiration
- Thread-safe token storage
- Configurable refresh window
- Token rotation support
Summary
Functions
Returns a specification to start this module under a supervisor.
Gets the current valid access token.
Gets full token information including metadata.
Forces an immediate token refresh.
Sets a new token in the manager.
Starts a token manager process.
Subscribes to token update notifications.
Unsubscribes from token update notifications.
Upgrades the token's scopes by merging additional scopes with the current ones.
Types
@type auth_method() :: :client_secret | :private_key_jwt | :enterprise_idjag
@type t() :: %ExMCP.Authorization.TokenManager{ access_token: String.t() | nil, auth_config: map(), auth_method: auth_method() | nil, expires_at: DateTime.t() | nil, refresh_timer: reference() | nil, refresh_token: String.t() | nil, scope: String.t() | nil, subscribers: MapSet.t(pid()), token_type: String.t() }
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec get_token(GenServer.server()) :: {:ok, String.t()} | {:error, atom()}
Gets the current valid access token.
Returns {:ok, token} or {:error, reason} if token is expired/missing.
@spec get_token_info(GenServer.server()) :: {:ok, map()} | {:error, atom()}
Gets full token information including metadata.
@spec refresh_now(GenServer.server()) :: {:ok, map()} | {:error, any()}
Forces an immediate token refresh.
@spec set_token(GenServer.server(), map()) :: :ok
Sets a new token in the manager.
@spec start_link(keyword()) :: GenServer.on_start()
Starts a token manager process.
Options:
:auth_config- Authorization configuration (client_id, client_secret, token_endpoint, etc.):refresh_window- Seconds before expiration to refresh (default: 300):name- Optional process name
@spec subscribe(GenServer.server()) :: :ok
Subscribes to token update notifications.
Subscribers receive {:token_updated, manager, token_info} messages.
@spec unsubscribe(GenServer.server()) :: :ok
Unsubscribes from token update notifications.
@spec upgrade_scopes(GenServer.server(), [String.t()], keyword()) :: {:ok, map()} | {:error, atom() | {atom(), [String.t()]}}
Upgrades the token's scopes by merging additional scopes with the current ones.
If a refresh token is available, attempts to refresh with the expanded scope set.
If no refresh token is available, returns {:error, :reauthorization_required}
with the combined scope list so the caller can initiate a full re-authorization.
Options
:timeout- Call timeout in milliseconds (default: 30_000)