# auth.md

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.
