# auth.md

## Protected resource

- resource: https://kannkidas.de/api
- authorization_servers: https://kannkidas.de
- scopes_supported: sponsorship:read sponsorship:write
- bearer_methods_supported: header

## OAuth authorization server

- issuer: https://kannkidas.de
- metadata: https://kannkidas.de/.well-known/oauth-authorization-server
- registration_endpoint: https://kannkidas.de/api/agent/register
- token_endpoint: https://kannkidas.de/api/oauth/token
- grant_types_supported: client_credentials
- token_endpoint_auth_methods_supported: client_secret_basic

## Step 1 — Discover

Read the protected-resource metadata and then the advertised OAuth authorization-server metadata. Its `agent_auth` block declares the anonymous registration method and the credential type this service really issues.

## Step 2 — Register an anonymous agent

Register with `POST /api/agent/register` and a JSON body containing a stable `name`. Registration grants only `sponsorship:read` by default; request `scopes: ["sponsorship:read", "sponsorship:write"]` explicitly only when the buyer intends to create a checkout. Registration is anonymous and returns a client secret exactly once. Store it as a secret. Exchange the credentials at the token endpoint using HTTP Basic authentication and `grant_type=client_credentials`; a missing `scope` parameter also defaults to read-only.

## Step 3 — Use the credential

Bearer tokens are short-lived, opaque credentials. Send them only in the `Authorization: Bearer …` header. Never place a client secret or token in a URL.

## Purchase guardrails

Before calling `POST /api/agent/purchases`, show the buyer the selected slot, the one-time net price of 990 EUR, the 30-day term and the sponsorship conditions. Require an explicit confirmation, send `buyer_confirmed: true` in the request body and reuse the same `Idempotency-Key` for retries. The server rejects a missing confirmation. Payment data belongs only on Stripe's hosted checkout page.
