# FastenerAtlas auth.md

AI agents can register an anonymous client, obtain an OAuth bearer access token,
and read their own registration. Public reference pages remain accessible without credentials.
Agent credentials never permit modification of reference data.

## Discover

- [Protected Resource Metadata](/.well-known/oauth-protected-resource)
- [Authorization Server Metadata](/.well-known/oauth-authorization-server)
- Issuer and resource: `https://fasteneratlas.com`
- Supported method: anonymous registration followed by OAuth `client_credentials`.
- Credential type: `access_token`; scope: `agent:read` (read your own registration).

This service implements the `agent_auth.register_uri` / `claim_uri` discovery
profile with standard OAuth client credentials. It does not implement the newer
WorkOS identity-assertion exchange, ID-JAG, verified-email registration, user SSO,
authorization-code grants, refresh tokens, or identity revocation events.

## Register: POST /agent/register

Send `Content-Type: application/json` with both required fields:

```json
{"type":"anonymous","client_name":"My reference assistant"}
```

`client_name` must contain 1–80 plain text characters. Do not include personal
information or secrets. Registration returns HTTP 201 with `client_id`,
`client_secret`, `client_name`, `client_id_issued_at`, `client_secret_expires_at`,
`scope`, `token_endpoint`, `token_endpoint_auth_method`, `grant_types`,
`claim_token`, `claim_expires_at`, and `claim_url`.
Timestamps are Unix seconds. Save credentials securely; secrets are shown once.
Each successful request creates a separate registration, including retries.
Client credentials expire after 24 hours. Register again after expiration.

This is the service's agent-registration API, not an RFC 7591 dynamic client
registration endpoint. No initial account, payment, email, or credential is required.

## Obtain credentials: POST /oauth/token

Authenticate using HTTP Basic with the issued `client_id` as username and
`client_secret` as password. Send `Content-Type: application/x-www-form-urlencoded`:

```text
grant_type=client_credentials&scope=agent%3Aread
```

The response contains `access_token`, `token_type: "Bearer"`, `expires_in`, and
`scope: "agent:read"`. Tokens last up to 3,600 seconds, capped at client expiry.
The optional `scope` defaults to the client's sole registered scope, `agent:read`.
There are at most 20 live tokens per client. Reuse a token until it expires or is
revoked; use the same client credentials to request another before client expiry.

## Use credentials

Send `Authorization: Bearer <access_token>` on GET or HEAD
`/api/v1/agent-registration`. It returns only that agent's `client_id`,
`client_name`, `created_at`, `expires_at`, and `scope`.
Credentials in URLs or query strings are rejected. Invalid, expired, and revoked
tokens receive HTTP 401 with a `WWW-Authenticate` discovery header.

## Optional ownership: POST /agent/claim

Anonymous registration is usable immediately. Offer the returned `claim_url` to
the user only if they want ownership and revocation control. Do not automatically
claim it on the user's behalf. The invitation expires in ten minutes.

The browser reads the invitation from the URL fragment, removes it from the URL,
and requires the user's explicit confirmation before sending:

```json
{"claim_token":"<claim_token from registration>"}
```

The endpoint atomically consumes the invitation, creates a pseudonymous owner,
and returns `owner_id`, `client_id`, `expires_at`, and a private `management_key`.
The user saves this management key to a private file. It is shown only once;
losing it means losing management access. There is no email recovery.
Claiming proves possession of the invitation, not a verified name, email, or human
identity, and does not increase the agent's scope. Ownership expires with the client.

The user can return to [Manage your agent](/agent/claim/) and enter their saved
key. GET `/api/v1/agent-owner` accepts it as `Authorization: Bearer <management_key>`
and returns `owner_id`, `client_id`, `expires_at`, and `revoked`.
POST `/agent/manage/revoke` with that same header and JSON `{}` permanently revokes
the entire client and all its tokens. The management key is never stored in browser storage.

## Revoke a token: POST /oauth/revoke

Use the same HTTP Basic client authentication as the token endpoint and send
`Content-Type: application/x-www-form-urlencoded`:

```text
token=<access_token>&token_type_hint=access_token
```

Revocation returns HTTP 200, including repeated revocation and unknown tokens,
and does not revoke another client's token. The client may obtain a new token.
Use owner revocation to invalidate the entire client instead.

## Limits and errors

Request bodies are limited to 8 KiB. Registration permits ten requests per peer
per minute and sixty globally per minute. Authenticated operations share a limit
of 120 requests per peer per minute and 600 globally. The server uses the network
peer address, so clients behind the same proxy share a limit. At most 10,000 active
clients are retained. HTTP 429 includes `Retry-After: 60`; retry after that delay.
Errors include problem details with `traceId` and field errors for HTTP 400. OAuth token and revocation errors use `application/json` with `error` and `error_description`; other API errors use `application/problem+json`.
No registration or credential POST should be made during a passive scan.

## Public documents

GET reference pages with `Accept: text/markdown`; HEAD returns headers only.
See [API documentation](/api-docs.md) and [OpenAPI specification](/openapi.json).
Follow each page's source, usage, and publication-status warnings.
