# auth.md

Gibeon exposes a tenant-scoped REST API and an MCP server at https://www.gibeon.io.
Authentication is OAuth 2.1 (Authorization Code + PKCE), issued by Supabase.

## Discover

- Protected resource metadata: https://www.gibeon.io/.well-known/oauth-protected-resource
- Authorization server metadata: https://cuztuwusnyvfuictgesw.supabase.co/.well-known/oauth-authorization-server/auth/v1
- MCP server card: https://www.gibeon.io/.well-known/mcp/server-card.json

## Register

Dynamic Client Registration (RFC 7591) is supported at the authorization server's
`registration_endpoint`, so a client can register itself with no human interaction.

## Authorize and consent

Authorization Code + PKCE. During consent the user chooses which tenant the agent may
access and grants the `gibeon:api` scope.

## Use

Send `Authorization: Bearer <access_token>` to https://www.gibeon.io/v1/* and /mcp.

## Refresh (headless / unattended)

Store the refresh token and exchange it for new access tokens without re-prompting.
This is the path for server and cron integrations, set up once by a human.

## Revoke

Revoke an agent from the Gibeon CMS (Settings, Connected apps), or via the
authorization server's revocation endpoint.

## Agentic registration (anonymous claim)

For an agent that cannot complete a browser redirect, the anonymous claim flow
issues a tenant-scoped token after one human approval.

1. Register a public PKCE client via Dynamic Client Registration, with
   `redirect_uris: ["https://www.gibeon.io/agent/callback"]` and
   `token_endpoint_auth_method: "none"`.
2. `POST https://www.gibeon.io/agent/claim` with `{ "client_id": "...", "email": "<the human's email>" }`.
   The response carries a `claim_token` plus a `claim_attempt` block with a
   6-digit `user_code` and a `verification_uri`.
3. Show the human the `verification_uri` and the `user_code`. They sign in, pick
   the tenant the agent may access, and type the code.
4. Poll `POST https://www.gibeon.io/agent/claim` with `{ "claim_token": "..." }`.
   Until the human finishes, the response is `{ "error": "authorization_pending" }`.
   On approval it returns the `access_token` (a Supabase-issued, tenant-scoped
   token) plus a `refresh_token`, once.
5. Use the `access_token` as in Use, refresh with the `refresh_token` as in
   Refresh, and revoke as in Revoke.
