# auth.md — Amaze Cph agent authentication

This document describes how AI agents authenticate to Amaze Cph's online store
at https://amazecph.dk, and what actually requires authentication versus
what does not. Every value below was read directly from the live endpoints
on 2026-08-28 — nothing here is inferred or templated.

## Summary

| What | Requires auth? | Mechanism |
|---|---|---|
| UCP/MCP catalog discovery (`initialize`, `tools/list`, `search_catalog`, `get_product`, `lookup_catalog`) | **No** | none — verified live, no `Authorization` header sent |
| UCP/MCP cart & checkout tools (`create_cart`, `create_checkout`, `complete_checkout`, …) | Buyer-context, not agent OAuth | see "Checkout is not an OAuth-gated action" below |
| Resources exposed under the OAuth-protected-resource metadata (customer-account-bound actions) | **Yes** | OAuth 2.0 (RFC 9728 protected-resource metadata → Shopify Customer Account authorization server) |
| UCP protocol-level agent identification (`resources/list`, `prompts/list`, and any tool call carrying `meta.ucp-agent`) | Not OAuth — a UCP profile URI | see "A second, non-OAuth gate" below |

## OAuth-protected resource metadata (RFC 9728)

`GET` on https://amazecph.dk/.well-known/oauth-protected-resource returns,
verbatim:

```json
{
  "resource": "https://amazecph.dk",
  "authorization_servers": ["https://shopify.com/authentication/78980284761"],
  "bearer_methods_supported": ["header"]
}
```

This declares one authorization server for the https://amazecph.dk resource,
and that bearer tokens are presented via the `Authorization` HTTP header
(RFC 6750 style, `Authorization: Bearer <token>`).

## Authorization server metadata (RFC 8414)

The declared authorization server publishes standard OAuth 2.0 Authorization
Server Metadata at:

`GET` on https://shopify.com/authentication/78980284761/.well-known/oauth-authorization-server

This **resolves** (HTTP 200) and returns, verbatim:

```json
{
  "issuer": "https://shopify.com/authentication/78980284761",
  "token_endpoint": "https://shopify.com/authentication/78980284761/oauth/token",
  "authorization_endpoint": "https://shopify.com/authentication/78980284761/oauth/authorize",
  "end_session_endpoint": "https://shopify.com/authentication/78980284761/logout",
  "jwks_uri": "https://shopify.com/authentication/78980284761/.well-known/jwks.json",
  "scopes_supported": ["openid", "email", "customer-account-api:full", "customer-account-mcp-api:full"],
  "response_types_supported": ["code"],
  "token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post"],
  "subject_types_supported": ["public"],
  "id_token_signing_alg_values_supported": ["RS256"],
  "claims_supported": ["iss", "sub", "aud", "exp", "iat", "nonce", "sid", "email", "email_verified"],
  "code_challenge_methods_supported": ["S256"],
  "grant_types_supported": ["authorization_code", "refresh_token", "urn:ietf:params:oauth:grant-type:jwt-bearer"],
  "op_policy_uri": "https://www.shopify.com/legal/privacy",
  "op_tos_uri": "https://www.shopify.com/legal/terms"
}
```

This is a standard OAuth 2.0 authorization-code flow (`response_types_supported: ["code"]`)
with PKCE (`code_challenge_methods_supported: ["S256"]`). The `scopes_supported`
list — `openid`, `email`, `customer-account-api:full`, `customer-account-mcp-api:full`
— is Shopify's **Customer Account API / Customer Account MCP** scope set. This
is buyer-identity authentication (the customer logging in and consenting to
let an agent act as them), not a merchant/API-key credential an agent holds
on its own behalf.

**What this is honestly for:** the `customer-account-mcp-api:full` scope name
strongly implies this authorization server exists to gate *customer-identity-bound*
MCP actions — e.g. an agent reading a specific signed-in customer's order
history — not the general product catalog. We have not been able to enumerate
which specific MCP tools or resources are gated behind it (Shopify does not
publish that mapping at a discoverable URL), so treat the table above as the
honest boundary: catalog discovery is open, and anything customer-identity-bound
should be assumed to need this OAuth flow until an agent tries it and gets a
`401`/`WWW-Authenticate` challenge naming this resource.

## Checkout is not an OAuth-gated action

`agents.md` (https://amazecph.dk/agents.md) states the operative rule
directly: **"Checkout requires human approval. Agents must not complete
payment without explicit buyer consent."** `complete_checkout` is reachable
over the same unauthenticated MCP transport as catalog search — the
constraint is a *behavioral* invariant enforced by protocol convention and
buyer-approval UX (Shop Pay / buyer-present confirmation), not an OAuth
scope check on the MCP call itself. Do not read the absence of a bearer-token
requirement on `complete_checkout` as license to complete a purchase without
the buyer explicitly present and consenting at the moment of payment.

## A second, non-OAuth gate: the UCP agent profile

Independently of OAuth, the UCP/MCP endpoint (https://a29d86.myshopify.com/api/ucp/mcp)
enforces a **UCP-protocol-level** requirement on some methods that is easy to
mistake for an auth failure. Calling `resources/list` or `prompts/list`
without a `meta.ucp-agent.profile` field returns:

```json
{"jsonrpc":"2.0","id":3,"error":{"code":-32001,"message":"UCP discovery failed","data":{"code":"invalid_profile_url","content":"Unable to fetch agent profile: Missing profile uri","continue_url":"https://a29d86.myshopify.com/"}}}
```

(verified live, 2026-08-28). This is UCP's own agent self-identification
mechanism — several tool schemas (e.g. `get_checkout`) declare a `meta.ucp-agent.profile`
object with a required `profile` URI — and is unrelated to the OAuth flow
described above. It is not a bearer token; it is a URI identifying the
calling agent, which the store then fetches to discover the agent's declared
capabilities. `initialize` and `tools/list` do not require it.

## Recommended flow for an agent

1. Call `POST /api/ucp/mcp` `initialize`, then `tools/list` — no credentials needed.
2. Use `search_catalog` / `lookup_catalog` / `get_product` freely — no credentials needed.
3. For cart and checkout tools, follow `agents.md`'s buyer-approval rule; do
   not attempt to acquire or use an OAuth bearer token to bypass buyer consent
   at the moment of payment — that is not what this authorization server is for.
4. If a call returns `401` with a `WWW-Authenticate` header naming
   https://amazecph.dk as the resource, that is the customer-identity OAuth
   flow above: send the customer through `authorization_endpoint`, and use the
   resulting token only on that customer's own behalf, never to authenticate
   the agent itself as a merchant credential.

## Sources (fetched live 2026-08-28)

- https://amazecph.dk/.well-known/oauth-protected-resource
- https://shopify.com/authentication/78980284761/.well-known/oauth-authorization-server
- https://amazecph.dk/agents.md
- https://a29d86.myshopify.com/api/ucp/mcp (`initialize`, `tools/list`, `resources/list` JSON-RPC calls)
