# tokyo.how auth.md — agent registration and public guide access

## Choose an access model

Public pages and `POST /mcp` remain anonymous: no registration, OAuth token, or API key is required. Use MCP to search and read public English and Japanese guides without credentials.

Agents that need a registered client identity can optionally use the **anonymous registration + OAuth device authorization** flow below. It issues a short-lived Bearer access token for `GET /api/agent/guides`, limited to `guides:read`. Registration and consent do not verify a person's identity or create a personal user account. No personal information, private account access, or editorial submission permission is granted.

## 1. Discover endpoints

Read `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server` from the same origin as this file. Use the advertised issuer, registration, device authorization, token, and revocation endpoints. On a preview host, use that preview origin throughout; do not send preview credentials to production.

The OAuth Authorization Server metadata includes an `agent_auth` block with `register_uri`, `claim_uri`, `identity_types_supported: ["anonymous"]`, and the supported credential type. This is a self-contained anonymous client-provisioning flow using OAuth RFC 8628; it does not support ID-JAG identity assertions, verified-email registration, refresh tokens, OIDC sign-in, or a user-owned WorkOS claim flow.

## 2. Register the anonymous agent

Only register when your user asks to connect a registered guide agent. Anonymous MCP access does not need this step.

```http
POST /api/agent/register
Content-Type: application/json

{"identity_type":"anonymous","client_name":"My Tokyo guide agent","scope":"guides:read"}
```

The response returns `client_id`, `client_secret`, `client_secret_expires_at`, and the supported device grant. Keep the client secret outside model prompts and conversation history. Client credentials expire after 24 hours. Client names are short labels, not email addresses or user identities.

## 3. Start the claim / device-consent ceremony

```http
POST /api/oauth/device
Content-Type: application/x-www-form-urlencoded

client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=guides%3Aread
```

This is the `agent_auth.claim_uri` endpoint. It returns `device_code`, `user_code`, `verification_uri`, `verification_uri_complete`, `expires_in` (up to 600 seconds), and `interval` (5 seconds).

Keep the device code secret. Show the user the verification link and user code, explain that approval is only for reading public guides, and have the user approve the request in their browser. Do not approve an unsolicited code or imply that approval verifies a person's identity. The verification page uses a same-origin POST and a CSRF cookie; it contains no analytics or advertising scripts.

## 4. Exchange the approved device code for an access token

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

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&device_code=YOUR_DEVICE_CODE
```

Wait at least `interval` seconds between attempts. `authorization_pending` means the user has not approved yet. For `slow_down`, increase the interval by 5 seconds. `expired_token` requires starting a new device ceremony. A device code can be exchanged successfully only once, including concurrent requests.

Success returns `access_token`, `token_type: "Bearer"`, `scope: "guides:read"`, and `expires_in` (up to 3600 seconds). Tokens cannot grant write access or access to private information. There is no refresh token; register again after client expiry.

## 5. Use the protected resource

```http
GET /api/agent/guides?q=suica&lang=en&limit=5
Authorization: Bearer YOUR_ACCESS_TOKEN
```

Use `slug=suica-card&lang=en` instead of `q` to retrieve the full article. Supply exactly one of `q` or `slug`; `lang` is `en` or `ja`, and `limit` is 1–10. Successful responses include the client identifier as `agent_id`, guide metadata, and canonical citation URLs. Invalid or expired tokens return HTTP 401 with `WWW-Authenticate` pointing to the protected resource metadata.

Cite the guide's canonical URL. Check official references for changing prices and eligibility.

## 6. Revoke the credential when finished

```http
POST /api/oauth/revoke
Content-Type: application/x-www-form-urlencoded

token=YOUR_ACCESS_TOKEN&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET
```

Revocation is idempotent and returns HTTP 200 for an unknown or already revoked token. A client can revoke only its own tokens. The service stores hashes of client secrets, device codes, and access tokens in private storage; it does not log them. Revocation is checked against strongly consistent storage on every protected request. Expiry is enforced by the application; storage objects are also removed by a one-day lifecycle rule.

## Other interfaces and side effects

- [A2A Agent Card](https://tokyo.how/.well-known/agent-card.json): stateless, read-only guide search/retrieval over A2A 1.0 JSON-RPC at `/api/a2a`.
- [Developer documentation](https://tokyo.how/developers): setup, schemas, limits, and versioning policy.
- `request_article` and `POST /api/article-request` submit an editorial request and may notify the operator. The `guides:read` token does not authorize them. Use them only when the user explicitly asks to submit a request.

Registration is limited to 10 requests per minute per client IP per Worker isolate; other public APIs have a shared best effort limit of 120 per minute. Respect RateLimit and Retry-After response headers. Infrastructure protection can add limits.

## Terms and contact

Use the [terms](https://tokyo.how/ja/terms), [privacy policy](https://tokyo.how/ja/privacy), and [contact page](https://tokyo.how/contact). Anonymous public access does not grant additional content-reuse rights.
