# RecipeBee auth.md

You are an agent. RecipeBee supports **agent_auth** discovery so you can read public recipes anonymously and obtain OAuth credentials before saving private recipes or meal plans. Follow Discover → Pick a method → Register → Claim → Exchange → Use the access_token. Do not skip ahead when a write requires a user.

This file is the `agent_auth.skill` document. Protected-resource metadata lives at [https://recipebee.app/.well-known/oauth-protected-resource](https://recipebee.app/.well-known/oauth-protected-resource). Authorization-server metadata lives at [https://recipebee.app/.well-known/oauth-authorization-server](https://recipebee.app/.well-known/oauth-authorization-server).

RecipeBee does not mint `identity_assertion` tokens or `urn:ietf:params:oauth:token-type:id-jag` ID-JAG grants. Do not send those assertion types. Use anonymous reads or OAuth authorization-code with PKCE for MCP writes.

## Discover

A missing or invalid bearer on MCP or `/agent/identity` returns:

```http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://recipebee.app/.well-known/oauth-protected-resource"
```

### 1a. Protected resource metadata

```http
GET https://recipebee.app/.well-known/oauth-protected-resource
```

Use `authorization_servers` from that document. Public catalog `GET https://recipebee.app/api` stays anonymous and returns 200.

### 1b. Authorization server metadata

```http
GET https://recipebee.app/.well-known/oauth-authorization-server
```

That document includes an `agent_auth` block with `skill` (this file) and `identity_endpoint` (`https://recipebee.app/agent/identity`). `identity_types_supported` is `anonymous`. RecipeBee does not advertise `service_auth` claim ceremonies or ID-JAG `identity_assertion` types.

The identity_endpoint URI is reachable (OPTIONS is not 404). GET or POST without a user session returns 401 with the WWW-Authenticate hint above. It does not issue ID-JAG-backed access tokens.

## Pick a method

1. **Anonymous public reads** — no credentials. Call `GET /api/v1/public/recipes` and other public GET endpoints. OpenAPI: [https://recipebee.app/openapi.json](https://recipebee.app/openapi.json).
2. **MCP writes (recommended for agents)** — OAuth 2.1 authorization code + PKCE against `authorization_endpoint`, `token_endpoint`, and optional `registration_endpoint`. Preview MCP tools stay anonymous.
3. **Private REST** — Laravel Sanctum session or bearer for the iPhone app and website. Agents should prefer MCP OAuth instead of scraping Sanctum cookies.

## Register

If authorization-server metadata includes `registration_endpoint`, register a public OAuth client:

```http
POST https://recipebee.app/oauth/register
```

Send `redirect_uris` for your host. Token endpoint auth method is `none` (public client). Use `code_challenge_method=S256`.

## Claim

RecipeBee does not run a separate WorkOS-style claim_endpoint for email device-code ownership. The user claims the account during the OAuth consent screen at `authorization_endpoint` (`https://recipebee.app/oauth/authorize`). If the user is not signed in, they sign in there. There is no `id-jag` path.

## Exchange

```http
POST https://recipebee.app/oauth/token
```

Use `grant_type=authorization_code` with `code`, `redirect_uri`, `code_verifier`, and the registered `client_id`. Refresh with `grant_type=refresh_token`. RecipeBee does not accept `urn:ietf:params:oauth:grant-type:jwt-bearer` ID-JAG assertions.

## Use the access_token

Send `Authorization: Bearer <access_token>` to the MCP resource at [https://recipebee.app/mcp](https://recipebee.app/mcp). Preview tools work without a token. Save, image, and meal-plan import tools require OAuth scopes advertised in protected-resource metadata.

For authenticated REST writes that support retries, send `Idempotency-Key` (and `X-Idempotency-Key` is also accepted on some endpoints). Replaying the same key must not double-create a recipe, meal plan, or image job.

## Errors

Invalid MCP tool names and arguments return JSON-RPC `error.code` and `error.message`. HTTP 401 includes WWW-Authenticate with `resource_metadata`. HTTP 403 with insufficient OAuth scope means the token is valid but missing a permission. HTTP 429 includes `Retry-After`. Public REST errors use a JSON object with a machine-readable `code` or `error` field and a human-readable `message`.

## Revocation

```http
POST https://recipebee.app/oauth/revoke
```

After revoke, do not retry writes with the old access_token. Ask the user to connect RecipeBee again.
