ExMCP.Authorization (ex_mcp v0.10.0)

View Source

MCP Authorization support for OAuth 2.1 with PKCE.

This is a cleaned-up version of the Authorization module that delegates to focused, single-responsibility modules:

This module serves as a facade, maintaining the same public API while leveraging the decomposed architecture for better maintainability.

Summary

Functions

Performs OAuth 2.1 client credentials flow.

Discovers server metadata from the authorization server.

Exchanges an authorization code for an access token using PKCE.

Generates PKCE code challenge parameters.

Starts an OAuth 2.1 authorization code flow with PKCE.

Makes a token request to the authorization server.

Validates an access token with the authorization server.

Types

authorization_config()

@type authorization_config() :: %{
  client_id: String.t(),
  client_secret: String.t() | nil,
  authorization_endpoint: String.t(),
  token_endpoint: String.t(),
  redirect_uri: String.t(),
  scopes: [String.t()],
  additional_params: map() | nil,
  resource: String.t() | [String.t()] | nil
}

server_metadata()

@type server_metadata() :: %{
  authorization_endpoint: String.t(),
  token_endpoint: String.t(),
  registration_endpoint: String.t() | nil,
  scopes_supported: [String.t()],
  response_types_supported: [String.t()],
  grant_types_supported: [String.t()],
  code_challenge_methods_supported: [String.t()]
}

token_response()

@type token_response() :: %{
  access_token: String.t(),
  token_type: String.t(),
  expires_in: integer() | nil,
  refresh_token: String.t() | nil,
  scope: String.t() | nil
}

Functions

client_credentials_flow(params)

@spec client_credentials_flow(map()) :: {:ok, token_response()} | {:error, term()}

Performs OAuth 2.1 client credentials flow.

Delegates to ExMCP.Authorization.OAuthFlow.client_credentials_flow/1

discover_server_metadata(issuer_url)

@spec discover_server_metadata(String.t()) ::
  {:ok, server_metadata()} | {:error, term()}

Discovers server metadata from the authorization server.

Uses HTTPClient for the actual HTTP request and metadata parsing.

exchange_code_for_token(params)

@spec exchange_code_for_token(map()) :: {:ok, token_response()} | {:error, term()}

Exchanges an authorization code for an access token using PKCE.

Delegates to ExMCP.Authorization.OAuthFlow.exchange_code_for_token/1

generate_pkce_challenge()

@spec generate_pkce_challenge() :: {:ok, String.t(), String.t()} | {:error, term()}

Generates PKCE code challenge parameters.

Delegates to the PKCE module.

refresh_token(refresh_token, client_id, token_endpoint, client_secret \\ nil)

@spec refresh_token(String.t(), String.t(), String.t(), String.t() | nil) ::
  {:ok, token_response()} | {:error, term()}

Refreshes an access token using a refresh token.

Delegates to ExMCP.Authorization.OAuthFlow.refresh_token/4

start_authorization_flow(config)

@spec start_authorization_flow(authorization_config()) ::
  {:ok, String.t(), map()} | {:error, term()}

Starts an OAuth 2.1 authorization code flow with PKCE.

Delegates to ExMCP.Authorization.OAuthFlow.start_authorization_flow/1 with the same interface and behavior.

token_request(config)

@spec token_request(map()) :: {:ok, map()} | {:error, any()}

Makes a token request to the authorization server.

Used internally by TokenManager for refresh operations. Delegates to HTTPClient for the actual request.

validate_token(token, introspection_endpoint)

@spec validate_token(String.t(), String.t()) :: {:ok, map()} | {:error, term()}

Validates an access token with the authorization server.

Uses HTTPClient for the introspection request.

verify_pkce_challenge(code_verifier, expected_challenge)

@spec verify_pkce_challenge(String.t(), String.t()) :: :ok | {:error, term()}

Verifies a PKCE code challenge.

Delegates to the PKCE module.