# geolith auth.md

You are an agent. This service supports **agentic registration**: discover → register → authorize (a person claims you) → exchange the code for an access token → call the API → handle revocation. Follow the steps in order; do not skip ahead.

The resource server is `https://api.geolith.app` (REST at `/v1/*`, MCP at `/mcp`, A2A at `/a2a`). The authorization server is `https://console.geolith.app`.

## Step 1 — Discover

A request without a credential gets a 401 with `WWW-Authenticate: Bearer resource_metadata="https://api.geolith.app/.well-known/oauth-protected-resource/mcp", scope="geocode"`.

1. Fetch the Protected Resource Metadata (RFC 9728): `https://api.geolith.app/.well-known/oauth-protected-resource/mcp` for MCP, `https://api.geolith.app/.well-known/oauth-protected-resource` for REST. `authorization_servers` is `["https://console.geolith.app"]`.
2. Fetch the Authorization Server metadata (RFC 8414): `https://console.geolith.app/.well-known/oauth-authorization-server`. Its `agent_auth` block carries this skill (`skill`), the registration endpoint (`register_uri`), `identity_types_supported: ["anonymous"]`, and `anonymous.claim_uri`.

## Step 2 — Register

Dynamic Client Registration (RFC 7591). POST your client metadata to `register_uri` (`https://console.geolith.app/api/auth/oauth2/register`); no initial access token is needed:

```http
POST https://console.geolith.app/api/auth/oauth2/register
Content-Type: application/json

{"client_name": "My agent", "redirect_uris": ["http://127.0.0.1:33418/callback"], "token_endpoint_auth_method": "none", "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"], "scope": "openid offline_access geocode"}
```

Keep the returned `client_id`. Public clients (`token_endpoint_auth_method: "none"`) must use PKCE.

## Step 3 — Authorize (claim)

Send the person who owns the geolith account to the authorization endpoint with PKCE (S256) and the resource you will call:

```
https://console.geolith.app/api/auth/oauth2/authorize?response_type=code&client_id=<client_id>&redirect_uri=<redirect_uri>&scope=openid%20offline_access%20geocode&resource=https%3A%2F%2Fapi.geolith.app%2Fmcp&code_challenge=<S256 challenge>&code_challenge_method=S256&state=<random>
```

They sign in (or create a free account) at https://console.geolith.app and approve your client on the consent screen. This claims your anonymous registration for their account; usage then counts against their monthly quota. They can see and revoke approved agents at https://console.geolith.app/dashboard/settings (the `claim_uri`).

## Step 4 — Exchange

POST the code to the token endpoint `https://console.geolith.app/api/auth/oauth2/token`:

```
grant_type=authorization_code&code=<code>&redirect_uri=<redirect_uri>&client_id=<client_id>&code_verifier=<verifier>&resource=https%3A%2F%2Fapi.geolith.app%2Fmcp
```

The access token is a JWT (one hour) signed with the keys at `https://console.geolith.app/api/auth/jwks`; `offline_access` also returns a refresh token. Use `resource=https://api.geolith.app` instead for the REST API.

## Step 5 — Use the access token

Call the API with `Authorization: Bearer <access_token>` (or `DPoP` with a proof if you bound the token):

- MCP: `POST https://api.geolith.app/mcp` (Streamable HTTP; tools `search`, `autocomplete`, `structured_search`, `reverse`, `place`).
- REST: `GET https://api.geolith.app/v1/search?text=…` (OpenAPI: https://docs.search.geolith.app/openapi.json).

Every call counts as one request against the account's monthly quota; `429` means the rate limit (see `Retry-After`) or the quota is used up.

To read the account's plan and this month's usage, ask for scope `usage` with `resource=https://console.geolith.app` and call `GET https://console.geolith.app/api/v1/usage` (metadata: `https://console.geolith.app/.well-known/oauth-protected-resource`).

## Alternative — API key

A person can create an API key at https://console.geolith.app/dashboard/keys and give it to you. Send it as `Authorization: Bearer gc_sk_…`. Keys work for REST, MCP and A2A.

## Revocation

Revoke tokens at the revocation endpoint (RFC 7009): `POST https://console.geolith.app/api/auth/oauth2/revoke` with `token` and `client_id`. When a person revokes your client at https://console.geolith.app/dashboard/settings, refreshing fails; access tokens already issued expire within an hour. Start again at Step 3 if you get `401 invalid_token`.
