# auth.md for Storeware

You are an agent. Storeware lets you register yourself and receive a credential to help a merchant run their shop, following the auth.md protocol (https://github.com/workos/auth.md). Follow these steps in order.

## Who this is for

This is for an agent acting for a **merchant**: a person who runs a shop on Storeware and wants you to work on it with them. What you receive reaches the merchant MCP server at https://api.storeware.ai/admin/mcp, where you can search and enrich products, read performance and search visibility, draft and revise pages, arrange menus and apply proposals. Nothing is ever published or deleted through it; the merchant does both in the Storeware admin.

If you are shopping for somebody at a Storeware shop instead, you are in the wrong place: read that shop's own `/auth.md`, on the shop's hostname.

## 1. Discover

The authorization server is https://api.storeware.ai. Its metadata is at https://api.storeware.ai/.well-known/oauth-authorization-server, and its `agent_auth` block is the current truth about what Storeware accepts; prefer it to anything cached from this page. Today it says:

```json
{
  "agent_auth": {
    "skill": "https://storeware.ai/auth.md",
    "identity_endpoint": "https://api.storeware.ai/api/mcp/agent/identity",
    "claim_endpoint": "https://api.storeware.ai/api/mcp/agent/identity/claim",
    "identity_types_supported": ["service_auth"],
    "register_uri": "https://api.storeware.ai/api/mcp/agent/identity",
    "claim_uri": "https://api.storeware.ai/api/mcp/agent/identity/claim"
  },
  "token_endpoint": "https://api.storeware.ai/api/mcp/oauth/token",
  "revocation_endpoint": "https://api.storeware.ai/api/mcp/oauth/revoke"
}
```

## 2. Choose a method

- **service_auth**: you know the email address the merchant signs in to Storeware with. Always available.
- **identity_assertion**: your agent provider can mint an ID-JAG for the merchant, and the metadata lists it in `identity_types_supported` with your provider's issuer in `identity_assertion.trusted_issuers`. Otherwise it is answered with `issuer_not_enabled`. See step 3.
- **anonymous**: not supported, and answered with `anonymous_not_enabled`. An unclaimed merchant agent would have no shop to act on.

Before you register, tell the merchant you are about to connect to their Storeware account as that address, and confirm with them.

## 3. Register

```http
POST https://api.storeware.ai/api/mcp/agent/identity
Content-Type: application/json

{ "type": "service_auth", "login_hint": "merchant@example.com" }
```

The response is the same whether or not that address has a Storeware account, and Storeware sends no email to it:

```json
{
  "registration_id": "…",
  "registration_type": "service_auth",
  "claim_url": "https://api.storeware.ai/api/mcp/agent/identity/claim",
  "claim_token": "clm_…",
  "claim_token_expires": "…",
  "post_claim_scopes": ["products:read", "…"],
  "claim": {
    "user_code": "123456",
    "verification_uri": "https://app.storeware.ai/agent/claim?claim_attempt_token=cat_…",
    "expires_in": 600,
    "interval": 5
  }
}
```

Keep `claim_token` secret. It is the only way to collect your credential.

With an identity assertion from a trusted provider instead, send:

```json
{ "type": "identity_assertion", "assertion_type": "urn:ietf:params:oauth:token-type:id-jag", "assertion": "<ID-JAG>" }
```

Mint it with `aud` https://api.storeware.ai, a verified email, a fresh `jti`, `auth_time`, and at most ten minutes of life. The first time, the answer is always a 401 `interaction_required` carrying the same claim block as above: the merchant confirms the link in the admin. After they have, the same provider subject gets an `identity_assertion` straight away: exchange it as step 7 shows. A 401 `login_required` means the merchant must sign in at your provider again.

## 4. Hand off to the merchant

Show the merchant the `verification_uri` and the six digit `user_code`, and ask them to open the link. They sign in to the Storeware admin as the address you named, choose which of their shops you may work on and whether you may change anything, and type the code. Only a person signed in as that exact address can complete it, and five wrong codes end the attempt.

If the code expires before they finish, ask for a new one with the same claim token and email:

```http
POST https://api.storeware.ai/api/mcp/agent/identity/claim
Content-Type: application/json

{ "claim_token": "clm_…", "email": "merchant@example.com" }
```

## 5. Poll for your credential

```http
POST https://api.storeware.ai/api/mcp/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=clm_…
```

Wait `interval` seconds between polls. While the merchant has not finished, the answer is `authorization_pending`; if you poll too fast it is `slow_down` and a longer interval; if the code or the claim window expired it is `expired_token`. Once they finish, you get this exactly once:

```json
{
  "access_token": "swm_…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "products:read orders:read …",
  "identity_assertion": "eyJ…",
  "assertion_expires": "…"
}
```

## 6. Use it

Send the access token as a bearer token to the merchant MCP server, over MCP streamable HTTP:

```http
POST https://api.storeware.ai/admin/mcp
Authorization: Bearer swm_…
```

The token lasts an hour and works only there. It holds the merchant MCP server's permissions narrowed to the role of the person who claimed you, and to reads unless they allowed changes.

## 7. Get a new token

Exchange your identity assertion. Every exchange checks again that the person who claimed you is still a member of that shop's organisation and may still connect apps to it; if not, you are refused with `invalid_grant` and your credential ends.

```http
POST https://api.storeware.ai/api/mcp/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=eyJ…&resource=https://api.storeware.ai/admin/mcp
```

The assertion lasts thirty days. After that, register again.

## 8. Revoke

When you are done, or asked to disconnect:

```http
POST https://api.storeware.ai/api/mcp/oauth/revoke
Content-Type: application/x-www-form-urlencoded

token=swm_…
```

The answer is always 200. The merchant can end your access at any time from the Agents screen in the admin.

## Errors

| Error | Where | What to do |
| --- | --- | --- |
| `anonymous_not_enabled` | registration | Use service_auth. |
| `issuer_not_enabled` | registration | Use service_auth. |
| `invalid_request` | anywhere | Fix the request as the description says. |
| `rate_limited` | registration | Wait before trying again. |
| `authorization_pending` | polling | Keep polling at the interval. |
| `slow_down` | polling | Poll less often. |
| `expired_token` | polling | Ask for a new code, or register again. |
| `invalid_grant` | token | Your claim or assertion is no longer good. Register again. |
| `invalid_target` | token | Ask for https://api.storeware.ai/admin/mcp, or omit resource. |
