# auth.md

You are an agent. Ninpo Snacks supports **agentic registration**: discover → register → (claim if needed) → exchange for an access_token → call API → handle revocation. Follow the steps in order; do not skip ahead.

## Service Overview

- **Service Name**: Ninpo Snacks
- **Audience**: Autonomous AI agents, personal shopper agents, customer ordering agents, fulfillment/delivery bots, and administrative operator systems.
- **Resource Server**: `https://api.ninposnacks.com`
- **Authorization Server**: `https://ninposnacks.com` (and `https://api.ninposnacks.com`)
- **Canonical Resource Identifier**: `https://api.ninposnacks.com/api/v1/mcp`
- **Protocols Supported**:
  - Model Context Protocol (MCP) — `https://api.ninposnacks.com/api/v1/mcp`
  - Universal Commerce Protocol (UCP) — `https://api.ninposnacks.com/ucp/v1`
  - Agentic Commerce Protocol (ACP) — `https://api.ninposnacks.com/acp/v1`
  - REST & UTCP APIs — `https://api.ninposnacks.com/api/v1`

---

## Step 1 — Discovery

Discovery follows RFC 9728 (OAuth 2.0 Protected Resource Metadata) and RFC 8414 (OAuth 2.0 Authorization Server Metadata).

### 1a. Protected Resource Metadata (PRM)

Fetch `/.well-known/oauth-protected-resource`:

```http
GET /.well-known/oauth-protected-resource HTTP/1.1
Host: ninposnacks.com
Accept: application/json
```

Response payload:

```json
{
  "resource": "https://api.ninposnacks.com/api/v1/mcp",
  "resource_name": "Ninpo Snacks",
  "authorization_servers": [
    "https://ninposnacks.com"
  ],
  "scopes_supported": [
    "mcp:read",
    "mcp:write",
    "catalog:read",
    "orders:create",
    "orders:read"
  ],
  "bearer_methods_supported": [
    "header"
  ]
}
```

Fields:
- `resource`: The canonical resource URI. Use this as the audience (`aud`) when minting assertions.
- `authorization_servers`: List of authorization servers issuing tokens for this resource.
- `scopes_supported`: List of supported OAuth permission scopes.
- `bearer_methods_supported`: Must include `"header"` (`Authorization: Bearer <token>`).

### 1b. Authorization Server Metadata

Fetch `/.well-known/oauth-authorization-server`:

```http
GET /.well-known/oauth-authorization-server HTTP/1.1
Host: ninposnacks.com
Accept: application/json
```

Response payload:

```json
{
  "issuer": "https://ninposnacks.com",
  "token_endpoint": "https://api.ninposnacks.com/oauth2/token",
  "revocation_endpoint": "https://api.ninposnacks.com/oauth2/revoke",
  "grant_types_supported": [
    "authorization_code",
    "urn:ietf:params:oauth:grant-type:jwt-bearer",
    "urn:workos:agent-auth:grant-type:claim"
  ],
  "agent_auth": {
    "skill": "https://ninposnacks.com/auth.md",
    "register_uri": "https://api.ninposnacks.com/agent/identity",
    "identity_endpoint": "https://api.ninposnacks.com/agent/identity",
    "claim_uri": "https://api.ninposnacks.com/agent/identity/claim",
    "claim_endpoint": "https://api.ninposnacks.com/agent/identity/claim",
    "revocation_uri": "https://api.ninposnacks.com/agent/identity/revoke",
    "events_endpoint": "https://api.ninposnacks.com/agent/event/notify",
    "identity_types_supported": [
      "identity_assertion",
      "anonymous"
    ],
    "identity_assertion": {
      "assertion_types_supported": [
        "urn:ietf:params:oauth:token-type:id-jag",
        "verified_email"
      ],
      "credential_types_supported": [
        "bearer_token",
        "api_key"
      ],
      "claim_uri": "https://api.ninposnacks.com/agent/identity/claim"
    },
    "anonymous": {
      "credential_types_supported": [
        "bearer_token",
        "session"
      ],
      "claim_uri": "https://api.ninposnacks.com/agent/identity/claim"
    },
    "events_supported": [
      "https://schemas.workos.com/events/agent/auth/identity/assertion/revoked"
    ]
  }
}
```

---

## Step 2 — Pick an Authentication Flow

Choose the appropriate flow based on your context:

1. **User Identity Session Available (ID-JAG)**
   - Type: `identity_assertion`
   - Assertion Type: `urn:ietf:params:oauth:token-type:id-jag`
   - Use when acting under an authenticated human user whose IdP can mint an Identity Assertion JWT Authorization Grant bound to `aud: https://api.ninposnacks.com/api/v1/mcp`.
2. **Verified Email**
   - Type: `identity_assertion`
   - Assertion Type: `verified_email`
   - Use when an email address has been verified; complete claim ceremony via the provided `claim_uri`.
3. **Anonymous / Guest Agent**
   - Type: `anonymous`
   - Use when browsing inventory, checking real-time stock, calculating delivery fees, or staging an unauthenticated cart. Claim ceremony can be deferred until order placement.
4. **Provisioned API Key**
   - Type: `bearer_token` / `api_key`
   - Customer Agent Key: `Authorization: Bearer np_agent_...`
   - Operator Key: `Authorization: Bearer np_live_...`

---

## Step 3 — Agent Registration

Submit registration payload to `agent_auth.register_uri` (`https://api.ninposnacks.com/agent/identity`).

### ID-JAG Assertion Flow

```http
POST /agent/identity HTTP/1.1
Host: api.ninposnacks.com
Content-Type: application/json

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

### Verified Email Flow

```http
POST /agent/identity HTTP/1.1
Host: api.ninposnacks.com
Content-Type: application/json

{
  "identity_type": "identity_assertion",
  "assertion_type": "verified_email",
  "email": "shopper@example.com"
}
```

### Anonymous Flow

```http
POST /agent/identity HTTP/1.1
Host: api.ninposnacks.com
Content-Type: application/json

{
  "identity_type": "anonymous"
}
```

### Registration Response

```json
{
  "status": "pending_exchange",
  "identity_assertion": "<service_signed_identity_assertion>",
  "claim_uri": "https://ninposnacks.com/claim?code=claim_123456",
  "expires_in": 300
}
```

---

## Step 4 — Token Exchange

Exchange the service-signed assertion at the token endpoint (`https://api.ninposnacks.com/oauth2/token`):

```http
POST /oauth2/token HTTP/1.1
Host: api.ninposnacks.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<service_signed_identity_assertion>
```

Response:

```json
{
  "access_token": "np_token_9f83a82e1c...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "catalog:read orders:create orders:read"
}
```

---

## Step 5 — Authenticated API Calls

Include the token in the `Authorization` header for all requests:

```http
GET /api/v1/catalog/products HTTP/1.1
Host: api.ninposnacks.com
Authorization: Bearer np_token_9f83a82e1c...
Accept: application/json
```

---

## Step 6 — Revocation & Lifecycle Events

To revoke credentials, send a revocation request:

```http
POST /agent/identity/revoke HTTP/1.1
Host: api.ninposnacks.com
Content-Type: application/x-www-form-urlencoded

token=np_token_9f83a82e1c...&token_type_hint=access_token
```

The service also supports Security Event Tokens (SET, RFC 8417) delivered to `agent_auth.events_endpoint` (`https://api.ninposnacks.com/agent/event/notify`) for asynchronous revocation:
- `https://schemas.workos.com/events/agent/auth/identity/assertion/revoked`
