# auth.md — Favorited Agency Dashboard MCP

Resource: https://mcp.agency.fav.com/mcp · Authorization server (issuer): https://id.fav.com · Version 1.0.0

This host is an OAuth 2.1 **resource server**. It issues nothing and accepts only access tokens minted by the issuer above, bound to one agency and one signed-in member. No API keys, no client secrets, no cookies, no Web Bot Auth — and no agent self-registration: a human grants every connection at consent (see "Not offered").

## 1. Discover

1. Protected Resource Metadata (RFC 9728): https://mcp.agency.fav.com/.well-known/oauth-protected-resource — also the path-specific form https://mcp.agency.fav.com/.well-known/oauth-protected-resource/mcp. Fields: resource, authorization_servers (["https://id.fav.com"]), scopes_supported (["agency:mcp:read", "agency:mcp:write"]), bearer_methods_supported (["header"]).
2. Authorization Server Metadata (RFC 8414): https://id.fav.com/.well-known/oauth-authorization-server — authorization, token, registration and revocation endpoints; code_challenge_methods_supported includes S256.

## 2. Register

- **Client ID Metadata Documents (preferred):** use an https URL that serves your client metadata JSON (echoing its own client_id, with your redirect_uris) as the client_id. Nothing to register in advance.
- **Dynamic client registration (RFC 7591):** POST https://id.fav.com/oauth2/register with redirect_uris, application_type and token_endpoint_auth_method "none". Public clients only; rate limited.
- **Pre-registered ids:** Claude, ChatGPT and Cursor are pre-registered with their published redirect URIs.

Registration creates an OAuth **client**, never an account or a credential: access is granted only in step 3, by a member, for one agency.

## 3. Authorize

GET https://id.fav.com/oauth2/auth?response_type=code&client_id=…&redirect_uri=…&code_challenge=…&code_challenge_method=S256&resource=https%3A%2F%2Fmcp.agency.fav.com%2Fmcp&scope=agency:mcp:read%20agency:mcp:write%20offline_access&state=…

- PKCE S256 is mandatory; resource is mandatory and must be exactly the resource above (RFC 8707).
- The member signs in with their Favorited account, picks the agency, sees the scopes in plain words, and chooses the access level (read / write / destructive) the agent may use within their own role. Write access is offered only when their role and the account allow it.
- The authorization response carries iss (RFC 9207). Codes are single-use and short-lived.

## 4. Use

- POST https://id.fav.com/oauth2/token with grant_type=authorization_code, the code, code_verifier, redirect_uri and resource → a short-lived access token (aud = the resource and the dashboard API) and, with offline_access, a refresh token.
- Send Authorization: Bearer <access token> to https://mcp.agency.fav.com/mcp. A 401 carries WWW-Authenticate: Bearer resource_metadata="https://mcp.agency.fav.com/.well-known/oauth-protected-resource", scope="agency:mcp:read"; a write on a read-only token answers 403 with error="insufficient_scope", scope="agency:mcp:read agency:mcp:write" — re-authorize once with both scopes.
- Refresh tokens rotate on every use; reusing a rotated token revokes the whole connection.

## 5. Revoke

- POST https://id.fav.com/oauth2/revoke with the refresh token, or the member disconnects the app under Settings → Access → Connected apps in the dashboard.
- A role change that removes a permission narrows the connection automatically; removing the member ends it.

## Not offered

- **Agentic self-registration (Auth.md agent_auth — anonymous, identity-assertion or service registration at a register endpoint):** not offered, by design. Every credential is delegated by a signed-in member for one agency at consent; there is no flow in which an agent obtains a credential without that human step, so the authorization server publishes no agent_auth block.
- Web Bot Auth (every route is public documentation or OAuth-protected), API keys, client secrets, multi-agency tokens.
- Direct machine access to the dashboard API: this server relays the member-delegated token to it, verbatim, under the same audience.
