# auth.md

> **Status: not live.** The authorization, token and identity endpoints described below return HTTP 501 today, and the JWKS document is an empty key set. This document describes the intended model so that discovery resolves and clients can prepare. Nothing here issues a credential yet.

You are an agent. This service publishes OAuth-based agent registration metadata. Follow the steps below to discover endpoints, register, and obtain credentials.

## Step 1 — Discover

### 1a. Fetch Protected Resource Metadata

```http
GET https://monogram.io/.well-known/oauth-protected-resource
```

Response fields:

- `resource` — canonical URL of this service (`https://monogram.io`). Use as `aud` when minting an ID-JAG.
- `resource_name` — display name for consent prompts.
- `authorization_servers` — base URLs of OAuth Authorization Servers for this resource.
- `scopes_supported` — scopes the resource server understands.
- `bearer_methods_supported` — send the access_token via `Authorization: Bearer …`.

### 1b. Fetch Authorization Server Metadata

```http
GET https://monogram.io/.well-known/oauth-authorization-server
```

The response includes standard RFC 8414 fields (`issuer`, `token_endpoint`, `revocation_endpoint`, `grant_types_supported`) plus an `agent_auth` block with:

- `agent_auth.skill` — URL of this document.
- `agent_auth.identity_endpoint` — `POST` here to register (Step 3).
- `agent_auth.claim_endpoint` — claim ceremony endpoint for anonymous/service_auth flows (Step 4).
- `agent_auth.identity_types_supported` — which registration methods this service accepts.
- `agent_auth.identity_assertion.assertion_types_supported` — assertion types accepted under `identity_assertion`.
- `agent_auth.events_supported` — event schemas the service can ingest (revocation SETs).

Token revocation is advertised at the top-level `revocation_endpoint` per RFC 7009.

## Step 2 — Pick a method

1. **You have a user session and can mint an audience-bound ID-JAG** → `identity_assertion` + `id-jag`.
2. **You have only the user's verified email** → `verified_email`. Claim ceremony required.
3. **You have neither** → `anonymous`. Claim ceremony is optional / deferred.

## Step 3 — Register

```http
POST https://monogram.io/agent/identity
Content-Type: application/json

{
  "type": "identity_assertion",
  "assertion_type": "urn:ietf:params:oauth:token-type:id-jag",
  "assertion": "<your ID-JAG JWT>"
}
```

For `verified_email`:

```http
POST https://monogram.io/agent/identity
Content-Type: application/json

{
  "type": "verified_email",
  "email": "user@example.com"
}
```

For `anonymous`:

```http
POST https://monogram.io/agent/identity
Content-Type: application/json

{ "type": "anonymous" }
```

## Step 4 — Claim ceremony

For `verified_email` and `anonymous` registrations the response includes a `claim_token` and RFC 8628-style ceremony materials (`user_code`, `verification_uri`, `expires_in`, `interval`).

Surface `verification_uri` + `user_code` to the user, then poll:

```http
POST https://monogram.io/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=<clm_...>
```

## Step 5 — Exchange the assertion

```http
POST https://monogram.io/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<identity_assertion>&resource=https://monogram.io
```

## Step 6 — Use the access_token

```http
GET https://monogram.io/api/some-resource
Authorization: Bearer <access_token>
```

When the access_token expires, repeat Step 5 with the same identity_assertion. When the assertion expires, restart at Step 3.

## Errors

| Code | Where | Action |
|------|-------|--------|
| `anonymous_not_enabled` | `/agent/identity` | Pick another method. |
| `issuer_not_enabled` | `/agent/identity` | Provider not trusted. Pick another method. |
| `invalid_request` | `/agent/identity` | Fix input or re-mint ID-JAG. |
| `interaction_required` | `/agent/identity` | ID-JAG matched existing account; complete claim ceremony. |
| `login_required` | `/agent/identity` | Re-authenticate at provider (`prompt=login`) and re-mint ID-JAG. |
| `invalid_grant` | `/oauth/token` | Assertion expired or revoked; restart at Step 3. |
| `authorization_pending` | `/oauth/token` | User hasn't finished ceremony; honor `interval` and retry. |
| `expired_token` | `/oauth/token` | Code window closed; re-initiate claim or restart at Step 3. |

## Revocation

- **Credential layer** — `POST https://monogram.io/oauth/revoke` with `token=<access_token>&token_type_hint=access_token`.
- **Registration layer** — provider POSTs an RFC 8417 SET to the service's events endpoint; all derived tokens are invalidated.
