# Authentication

> How Figgshield authenticates: SSO sign-in (Google, Apple, GitHub), OAuth 2.1 for the MCP connector and CLI, and personal API keys (Authorization: Bearer figg_...) for the CLI and REST.

Figgshield has three ways in, for three purposes:

| Purpose | Mechanism |
| --- | --- |
| Sign in to the web app | **SSO** — Google, Apple or GitHub |
| Connect Claude or the Claude Code CLI | **OAuth 2.1** (browser sign-in, PKCE) |
| CLI header or the REST API | **Personal API key** (`Authorization: Bearer figg_...`) |

There is no email/password sign-in and no email one-time-code step — sign-in is SSO only.

## Signing in (SSO)

The web app authenticates with one of three identity providers: **Google, Apple and GitHub**. Sign-in creates or links your account by email and sets an HttpOnly session cookie named `token`; the app uses that cookie for account, plan and key management. There is nothing to configure — pick a provider on the sign-in screen.

`GET /authentication/social/config/` reports which providers are available, so the app can hide any that are not configured:

```bash
curl https://api.figgshield.ai/authentication/social/config/
```

```json
{ "google": true, "apple": true, "github": true }
```

The current user is read with `GET /authentication/me/` (session cookie), and `POST /authentication/logout/` clears the cookie.

## OAuth for the connector and CLI

Adding Figgshield to **Claude** (as a connector) or the **Claude Code CLI** uses OAuth 2.1, not a session cookie. Figgshield is the authorization server; Google, Apple and GitHub are the upstream identity providers it federates to. You never paste a token — the client runs the flow:

1. The client requests `https://api.figgshield.ai/mcp` unauthenticated and receives `401` with a `WWW-Authenticate` header pointing at the protected-resource metadata.
2. It discovers the authorization server, then opens a browser for you to sign in (SSO) and approve the scopes `figgshield:read` and `figgshield:write`.
3. It exchanges an authorization code (PKCE, S256) for a JWT access token and refreshes it automatically.

Discovery documents:

| Document | URL |
| --- | --- |
| Protected resource metadata (RFC 9728) | `https://api.figgshield.ai/.well-known/oauth-protected-resource` |
| Authorization server metadata (RFC 8414) | `https://api.figgshield.ai/.well-known/oauth-authorization-server` |
| JWKS | `https://api.figgshield.ai/jwks.json` |

See [MCP server & tools](https://figgshield.ai/documentation/mcp.md) and [Claude Code CLI](https://figgshield.ai/documentation/cli.md) for the client-side steps. Claude registers itself automatically (Dynamic Client Registration), so private connectors need no manual client setup.

## Personal API keys

An API key authenticates the **Claude Code CLI** (as a header) and the **REST API** without a browser flow. A key acts with the same permissions as the account that owns it.

Create keys in the app under **Account → API keys**. A key looks like `figg_` followed by 40 hex characters:

```text
figg_1f2e3d4c5b6a79880716253443526170817263f4
```

The full secret is shown **once**, at creation — Figgshield stores only a SHA-256 hash and the first 12 characters as a display `prefix`. If you lose a key, revoke it and create a new one. An account can hold at most **20 active keys**.

Send the key on every request with the `Authorization: Bearer` header (or `X-API-Key`):

```bash
curl https://api.figgshield.ai/api/models/ \
  -H "Authorization: Bearer $FIGGSHIELD_API_KEY"
```

For the Claude Code CLI, pass it when you add the server:

```bash
claude mcp add --transport http figgshield https://api.figgshield.ai/mcp \
  --header "Authorization: Bearer figg_your_api_key_here"
```

A revoked or unknown key returns `401` with the machine code `invalid_api_key`:

```json
{ "error": "invalid_api_key", "detail": "This API key is invalid or has been revoked." }
```

### Managing keys over the REST API

Key management also works over the API, so keys can rotate keys. Each call accepts a session cookie or an API key.

```bash
# Create
curl https://api.figgshield.ai/api/keys/create/ -X POST \
  -H "Authorization: Bearer $FIGGSHIELD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "ci-pipeline" }'

# List
curl https://api.figgshield.ai/api/keys/ \
  -H "Authorization: Bearer $FIGGSHIELD_API_KEY"

# Revoke
curl https://api.figgshield.ai/api/keys/<uuid>/revoke/ -X POST \
  -H "Authorization: Bearer $FIGGSHIELD_API_KEY"
```

Create returns `201` and is the only response that ever contains the full `key`. List returns the standard envelope with `uuid`, `name`, `prefix`, `last_used_at`, `revoked` and `created_at` — never the secret. Revoke returns `200 {"revoked": true}`, is idempotent, and frees the key from the 20-key cap.

## Session cookies (browser)

The web app authenticates with the HttpOnly `token` cookie set at SSO sign-in and cleared by `POST /authentication/logout/`. Browser clients send it automatically with `credentials: "include"`. The cookie is for the account screens; programmatic clients should use OAuth (for MCP) or an API key (for the CLI header and REST).
