# FereAI Gateway — Authentication

The FereAI gateway (`https://stag-api.fereai.xyz`) accepts two authentication schemes. Both produce a bearer token used in the `Authorization: Bearer <token>` header on every protected request.

> **Quick discovery:**
> - OAuth Protected Resource metadata: <https://stag-api.fereai.xyz/.well-known/oauth-protected-resource>
> - OAuth Authorization Server metadata: <https://stag-api.fereai.xyz/.well-known/oauth-authorization-server>
> - MCP Server Card: <https://stag-api.fereai.xyz/.well-known/mcp/server-card.json>
> - API Catalog (RFC 9727): <https://stag-api.fereai.xyz/.well-known/api-catalog>

---

## 1. AgentDoor (Ed25519 challenge-response) — recommended for agents

AgentDoor is FereAI's native, account-less auth flow. An agent generates an Ed25519 keypair locally, registers the public key once, then exchanges signed challenges for bearer tokens. There is no human consent screen, no OAuth redirect, and no email — ideal for unattended agents.

### Tokens
- Prefix: `agt_*`
- Header: `Authorization: Bearer agt_<...>`
- Lifetime: short-lived (re-issue via `/v1/auth/token`)

### Flow

1. **Register** (one-time, returns a signing challenge)
   ```http
   POST /v1/auth/register
   Content-Type: application/json

   { "public_key": "<base64 Ed25519 public key>" }
   ```
   Response:
   ```json
   { "challenge": "<bytes>", "nonce": "<uuid>" }
   ```

2. **Verify** (prove possession of the private key)
   ```http
   POST /v1/auth/verify
   Content-Type: application/json

   {
     "nonce": "<uuid from step 1>",
     "signature": "<base64 Ed25519 signature over challenge>"
   }
   ```
   Response:
   ```json
   { "agent_id": "agt_..." }
   ```

3. **Token** (issue a bearer token; repeat as needed)
   ```http
   POST /v1/auth/token
   Content-Type: application/json

   {
     "agent_id": "agt_...",
     "timestamp": 1717180000,
     "signature": "<base64 Ed25519 signature over agent_id||timestamp>"
   }
   ```
   Response:
   ```json
   { "token": "agt_...", "expires_in": 3600 }
   ```

### Environment-variable shortcut
For local/CI usage, the SDK and MCP server will auto-issue tokens when both are set:

```bash
export FERE_AGENT_ID=agt_...
export FERE_SECRET_KEY=<base64 Ed25519 secret>
```

---

## 2. Clerk OAuth 2.1 + PKCE — recommended for human-bound agents

When the agent acts on behalf of an authenticated human (e.g. a Claude or ChatGPT integration), use Clerk OAuth. Tokens are standard JWTs that the gateway validates against Clerk's JWKS.

### Tokens
- Prefix: `eyJ...` (JWT)
- Header: `Authorization: Bearer eyJ...`
- Issuer: published in the OAuth AS metadata document.

### Endpoints (proxied through the gateway)
| Endpoint | Purpose |
|---|---|
| `/oauth/authorize` | User-consent / PKCE start |
| `/oauth/token` | Token exchange |
| `/oauth/register` | Dynamic Client Registration (RFC 7591) proxy |

### Scopes
`openid profile email offline_access`

### Discovery
- `/.well-known/oauth-protected-resource` — declares this gateway as a protected resource and points at the AS metadata (RFC 9728).
- `/.well-known/oauth-authorization-server` — proxies Clerk's AS metadata, substituting our DCR endpoint (RFC 8414).
- On 401, protected endpoints return:
  ```
  WWW-Authenticate: Bearer resource_metadata="https://stag-api.fereai.xyz/.well-known/oauth-protected-resource"
  ```

---

## Picking a scheme

| Scenario | Use |
|---|---|
| Headless agent, no human user | **AgentDoor** |
| Claude / ChatGPT plug-in acting for a human | **Clerk OAuth** |
| MCP client (Claude Desktop, etc.) | Either — both accepted on `/mcp`, `/mcp/sse`, `/mcp/messages` |
| CLI / scripted SDK usage | **AgentDoor** (export `FERE_AGENT_ID` + `FERE_SECRET_KEY`) |

---

## References

- RFC 9728 — OAuth 2.0 Protected Resource Metadata
- RFC 8414 — OAuth 2.0 Authorization Server Metadata
- RFC 7591 — OAuth 2.0 Dynamic Client Registration
- MCP Auth spec — <https://modelcontextprotocol.io/specification/draft/basic/authorization>
