# `ExMCP.Authorization.FullOAuthFlow`
[🔗](https://github.com/azmaveth/ex_mcp/blob/v1.0.0/lib/ex_mcp/authorization/full_oauth_flow.ex#L1)

Full OAuth 2.1 authorization code flow with PKCE for MCP.

Orchestrates the complete browser-based OAuth flow:

1. Discover Protected Resource Metadata (RFC 9728)
2. Discover Authorization Server metadata (RFC 8414 / OIDC)
3. Dynamic Client Registration (RFC 7591) if no client_id
4. Authorization Code flow with PKCE (RFC 7636)
5. Local redirect URI server to receive callback
6. Token exchange at token endpoint

This is used when a server returns 401 and the client has no
pre-existing credentials. For clients with credentials, use
`ExMCP.Authorization.DiscoveryFlow` instead.

## Usage

    {:ok, token} = FullOAuthFlow.execute(%{
      resource_url: "http://localhost:3000/mcp",
      client_registration: :auto,
      application_type: :native,
      redirect_port: 8080
    })

# `config`

```elixir
@type config() :: %{
  :resource_url =&gt; String.t(),
  optional(:client_id) =&gt; String.t(),
  optional(:client_secret) =&gt; String.t(),
  optional(:client_registration) =&gt;
    ExMCP.Authorization.RegistrationPolicy.configured_strategy(),
  optional(:credential_issuer) =&gt; String.t(),
  optional(:credential_store) =&gt; ExMCP.Authorization.CredentialStore.store(),
  optional(:credential_context) =&gt; term(),
  optional(:client_metadata_url) =&gt; String.t(),
  optional(:application_type) =&gt;
    ExMCP.Authorization.RegistrationPolicy.application_type(),
  optional(:redirect_port) =&gt; non_neg_integer(),
  optional(:private_key) =&gt; JOSE.JWK.t(),
  optional(:signing_algorithm) =&gt; String.t(),
  optional(:key_id) =&gt; String.t(),
  optional(:scopes) =&gt; [String.t()],
  optional(:resource) =&gt; String.t() | [String.t()],
  optional(:http_client) =&gt; module() | function(),
  optional(:metadata_fetch) =&gt; keyword(),
  optional(:oauth_http) =&gt; keyword(),
  optional(:authorization_max_redirects) =&gt; 0..10,
  optional(:authorization_deadline_ms) =&gt; 1..60000,
  optional(:www_authenticate) =&gt; String.t(),
  optional(:protocol_version) =&gt; String.t()
}
```

# `execute`

```elixir
@spec execute(config()) :: {:ok, map()} | {:error, term()}
```

Execute the full OAuth flow.

Returns `{:ok, %{access_token: "...", ...}}` on success.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
