import {
  DocsTitle,
  DocsLead,
  DocsH2,
  DocsP,
  DocsList,
  DocsLi,
  DocsCode,
  Mono,
} from '@/components/docs-page';

export const metadata = { title: 'OAuth 2.1 flow — BuildMyMCPServer docs' };

export default function OAuthDocs() {
  return (
    <>
      <DocsTitle kicker="Auth">OAuth 2.1 flow</DocsTitle>
      <DocsLead>
        Every generated server is an OAuth 2.1 Resource Server. The control plane is the
        Authorization Server. Dynamic Client Registration, PKCE, and Resource Indicators per the
        2025 MCP authorization spec.
      </DocsLead>

      <DocsH2 id="rfcs">Standards we follow</DocsH2>
      <DocsList>
        <DocsLi>OAuth 2.1 draft (<Mono>draft-ietf-oauth-v2-1</Mono>) — no implicit, mandatory PKCE</DocsLi>
        <DocsLi>RFC 8414 — Authorization Server Metadata at <Mono>/.well-known/oauth-authorization-server/oauth</Mono></DocsLi>
        <DocsLi>RFC 9728 — Protected Resource Metadata at <Mono>/.well-known/oauth-protected-resource/&lt;server-path&gt;</Mono></DocsLi>
        <DocsLi>RFC 8707 — Resource Indicators (audience binding)</DocsLi>
        <DocsLi>RFC 7591 — Dynamic Client Registration</DocsLi>
      </DocsList>

      <DocsH2 id="walkthrough">End-to-end walkthrough</DocsH2>
      <DocsP>
        First request from a fresh client to a fresh server is unauthenticated. The server
        replies with a <Mono>401</Mono> plus a <Mono>WWW-Authenticate</Mono> header pointing to
        its resource metadata.
      </DocsP>
      <DocsCode
        label="step 1 — 401 challenge"
        code={`$ curl -i http://localhost:4103/mcp -d '{}' -H 'content-type: application/json'

HTTP/1.1 401 Unauthorized
www-authenticate: Bearer resource_metadata="http://localhost:4103/.well-known/oauth-protected-resource/mcp"
content-type: application/json

{"error":"unauthorized"}`}
      />

      <DocsP>
        The client fetches that resource metadata, sees the authorization server, then fetches the
        AS metadata to discover registration, authorize, token and JWKS endpoints.
      </DocsP>
      <DocsCode
        label="step 2 — resource metadata"
        code={`$ curl http://localhost:4103/.well-known/oauth-protected-resource/mcp

{
  "resource": "http://localhost:4103/mcp",
  "authorization_servers": ["http://localhost:4000/oauth"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["mcp:read"]
}`}
      />

      <DocsP>
        The client registers itself dynamically. No human in the loop, no preconfigured client
        IDs. Each AI surface gets its own ephemeral identity.
      </DocsP>
      <DocsCode
        label="step 3 — dynamic registration"
        code={`POST /oauth/register HTTP/1.1
{
  "client_name": "Claude Desktop",
  "redirect_uris": ["claude://oauth/callback"],
  "token_endpoint_auth_method": "none",
  "resource": "http://localhost:4103/mcp"
}

201 Created
{ "client_id": "bmm_8aee2fe0…", "redirect_uris": […] }`}
      />

      <DocsP>
        Authorization Code with PKCE. The user gives consent, the AS returns a one-time code,
        the client exchanges it for an RS256-signed JWT bound to the resource (audience).
      </DocsP>
      <DocsCode
        label="step 4 — token exchange"
        code={`POST /oauth/token HTTP/1.1
{
  "grant_type": "authorization_code",
  "code": "4uNk_SCU8…",
  "code_verifier": "riSU-w1DT…",
  "client_id": "bmm_8aee2fe0…",
  "redirect_uri": "claude://oauth/callback",
  "resource": "http://localhost:4103/mcp"
}

200 OK
{
  "access_token": "eyJ…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "pQR…"
}`}
      />

      <DocsP>
        Subsequent <Mono>/mcp</Mono> calls carry the JWT. The runner verifies the signature
        against the AS&apos;s JWKS, checks the <Mono>iss</Mono>, the <Mono>aud</Mono>
        (RFC 8707 — must match the runner&apos;s MCP resource URL), and the expiry. No token
        passthrough; the runner never forwards the client&apos;s token to a downstream API.
      </DocsP>

      <DocsH2 id="security">Why this matters</DocsH2>
      <DocsP>
        Without audience binding, a token issued for one customer&apos;s MCP server could be
        replayed against another customer&apos;s server. RFC 8707 closes that. Without PKCE, a
        public OAuth client on a desktop is exposed to interception of the authorization code.
        OAuth 2.1 closes that.
      </DocsP>
    </>
  );
}
