MCP.OAuth2.Client (fnord v0.8.71)
View SourcePure OAuth2 + PKCE client implementation for MCP servers.
Unlike OIDC libraries (like oidcc), this works with OAuth2 Authorization Server
discovery (RFC 8414) at /.well-known/oauth-authorization-server, not just
OpenID Connect discovery at /.well-known/openid-configuration.
Implements:
- Authorization Code flow with PKCE (RFC 7636)
- Token refresh (RFC 6749)
- OAuth2 server metadata discovery (RFC 8414)
Security:
- PKCE is always required (S256 challenge method)
- Tokens are never logged
- Uses secure random generation for state and verifier
Summary
Functions
Handle OAuth2 callback and exchange authorization code for tokens.
Refresh an expired access token using the refresh token.
Start OAuth2 authorization flow with PKCE.
Types
@type tokens() :: %{ access_token: String.t(), token_type: String.t(), expires_at: non_neg_integer(), refresh_token: String.t() | nil, scope: String.t() | nil }
Functions
@spec handle_callback(config(), map(), String.t(), String.t()) :: {:ok, tokens()} | {:error, term()}
Handle OAuth2 callback and exchange authorization code for tokens.
Validates state, extracts code, exchanges for tokens with PKCE verifier.
Returns: {:ok, tokens} with normalized token map
Refresh an expired access token using the refresh token.
Returns: {:ok, tokens} with new access token and possibly new refresh token
@spec start_flow(config()) :: {:ok, %{auth_url: String.t(), state: String.t(), code_verifier: String.t()}} | {:error, term()}
Start OAuth2 authorization flow with PKCE.
Fetches server metadata, generates PKCE parameters, and builds authorization URL.
Returns: {:ok, %{auth_url: String.t(), state: String.t(), code_verifier: String.t()}}