ExMCP.Authorization.ServerGuard (ex_mcp v0.9.2)

View Source

OAuth 2.1 Resource Server guard for validating bearer tokens.

This module provides functionality for an MCP server acting as an OAuth 2.1 Resource Server to validate incoming requests containing bearer tokens. It implements the validation logic as specified in RFC 6750.

Features

  • Extracts bearer tokens from the Authorization header.
  • Validates tokens using OAuth 2.0 Token Introspection (RFC 7662).
  • Performs scope-based access control.
  • Generates appropriate WWW-Authenticate error responses.
  • Integrates with ExMCP.FeatureFlags to be enabled/disabled.

Usage

This module is typically used in an MCP server's request processing pipeline, for example, in a Plug or before a message handler.

def handle_request(conn, required_scopes) do
  auth_config = %{
    introspection_endpoint: "https://auth.example.com/introspect",
    realm: "mcp-server"
  }

  case ExMCP.Authorization.ServerGuard.authorize(conn.req_headers, required_scopes, auth_config) do
    {:ok, token_info} ->
      # Authorization successful, proceed with processing
      # token_info contains claims about the token
      process_authorized_request(conn, token_info)

    {:error, {status, www_auth_header, body}} ->
      # Authorization failed, send error response
      conn
      |> put_resp_header("www-authenticate", www_auth_header)
      |> send_resp(status, body)
  end
end

Summary

Functions

Authorizes a request by validating the bearer token and checking scopes.

Extracts a bearer token from the Authorization header.

Types

auth_config()

@type auth_config() :: %{
  :introspection_endpoint => String.t(),
  optional(:realm) => String.t()
}

error_response()

@type error_response() :: {integer(), String.t(), String.t()}

token_info()

@type token_info() :: map()

Functions

authorize(headers, required_scopes, config)

@spec authorize(map() | list(), [String.t()], auth_config()) ::
  {:ok, token_info()} | {:error, error_response()} | :ok

Authorizes a request by validating the bearer token and checking scopes.

This is the main entry point for the guard. It performs the following steps:

  1. Checks if OAuth 2.1 authorization is enabled via feature flags.
  2. Extracts the bearer token from the Authorization header.
  3. Validates the token using the introspection endpoint.
  4. Verifies that the token's scopes include all required scopes.

Parameters

  • headers: A map or list of request headers.
  • required_scopes: A list of scope strings required for the operation.
  • config: Authorization configuration containing :introspection_endpoint and optional :realm.

Return Value

  • {:ok, token_info}: If authorization is successful. token_info is the map returned from the introspection endpoint.
  • {:error, error_response}: If authorization fails. error_response is a tuple {status_code, www_authenticate_header, body}.
  • :ok: If authorization is disabled via feature flags.

extract_bearer_token(headers)

@spec extract_bearer_token(map() | list()) ::
  {:ok, String.t()} | {:error, :missing_token}

Extracts a bearer token from the Authorization header.