# auth.md

You are an agent. Have I Been Pwned MCP uses OAuth 2.0 dynamic client registration plus Authorization Code with PKCE for agent access. This service does not support anonymous registration, verified-email claim ceremonies, or ID-JAG identity assertions.

Real endpoints for this host:

- Resource server: `https://haveibeenpwned.com/mcp`
- Protected Resource Metadata: `https://haveibeenpwned.com/.well-known/oauth-protected-resource`
- Authorization Server metadata: `https://haveibeenpwned.com/.well-known/oauth-authorization-server`
- Dynamic client registration: `https://haveibeenpwned.com/connect/register`
- Authorization endpoint: `https://haveibeenpwned.com/connect/authorize`
- Token endpoint: `https://haveibeenpwned.com/connect/token`

## Step 1 - Discover

Start with the Protected Resource Metadata:

```http
GET /.well-known/oauth-protected-resource
```

It advertises the MCP resource, the authorization server, the supported scope (`hibp.mcp`), and bearer token usage via the `Authorization` header.

Then fetch the Authorization Server metadata:

```http
GET /.well-known/oauth-authorization-server
```

Use the standard OAuth metadata fields as the source of truth:

- `registration_endpoint` for dynamic client registration
- `authorization_endpoint` for the user-facing OAuth authorization request
- `token_endpoint` for code and refresh token exchange
- `token_endpoint_auth_methods_supported` should be `["none"]`
- `agent_auth` summarizes the same interactive registration flow for agents and points back to this document

## Step 2 - Register a public OAuth client

Register a public client with at least one HTTPS redirect URI (localhost is also accepted for local development):

```http
POST /connect/register
Content-Type: application/json
```

```json
{
  "client_name": "Example HIBP MCP client",
  "redirect_uris": ["https://agent.example.com/oauth/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}
```

Successful registration returns a `client_id`. Store it and keep using PKCE; confidential clients and client secrets are not supported.

## Step 3 - Send the user through authorization

Build an authorization request for the MCP resource. The user must sign into their Have I Been Pwned dashboard account and grant consent interactively.

```http
GET /connect/authorize?response_type=code&client_id=<client_id>&redirect_uri=<redirect_uri>&scope=openid%20offline_access%20hibp.mcp&resource=https://haveibeenpwned.com/mcp&code_challenge=<pkce_challenge>&code_challenge_method=S256
```

Notes:

- `resource` must target `https://haveibeenpwned.com/mcp`
- `scope` must include `openid`, `offline_access`, and `hibp.mcp`
- PKCE with `S256` is required
- `prompt=none` will fail if the user is not already signed in or has not already granted consent

## Step 4 - Exchange the authorization code

Exchange the returned code at the token endpoint:

```http
POST /connect/token
Content-Type: application/x-www-form-urlencoded
```

```text
grant_type=authorization_code
&client_id=<client_id>
&code=<authorization_code>
&redirect_uri=<redirect_uri>
&code_verifier=<pkce_verifier>
```

The token response includes an access token for the MCP resource. If a refresh token is issued, you may later exchange it at the same token endpoint with:

```text
grant_type=refresh_token
&client_id=<client_id>
&refresh_token=<refresh_token>
```

## Step 5 - Call the MCP endpoint

Present the access token as a bearer token:

```http
POST /mcp
Authorization: Bearer <access_token>
```

If the MCP endpoint returns `401 Unauthorized`, discard the credential and restart from discovery. If a refresh token stops working, restart from registration and authorization as needed.

## Supported registration model

This service currently supports one agent registration model:

- `interactive_session`: register a public OAuth client, then complete an interactive Authorization Code + PKCE flow with the user

The service does **not** currently support:

- `anonymous` registration
- `identity_assertion` registration with `verified_email`
- `identity_assertion` registration with `urn:ietf:params:oauth:token-type:id-jag`
- claim or revocation endpoints for agent-specific registration state machines

## References

- Protected Resource Metadata: `https://haveibeenpwned.com/.well-known/oauth-protected-resource`
- Authorization Server metadata: `https://haveibeenpwned.com/.well-known/oauth-authorization-server`
- API documentation: `https://haveibeenpwned.com/API/V3`
- Terms of Use: `https://haveibeenpwned.com/TermsOfUse`
- Privacy policy: `https://haveibeenpwned.com/Privacy`
- Agent skill: `https://haveibeenpwned.com/.well-known/agent-skills/hibp-mcp/SKILL.md`