> ## Documentation Index
> Fetch the complete documentation index at: https://docs.browsary.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication & security

> Pick the right auth mechanism for each integration and understand the extra requirements enforced by the Browsary middleware.

Browsary exposes multiple authentication layers so humans can use cookies in the dashboard while services rely on scoped API keys. Several endpoints also demand email verification or completed two-factor authentication (2FA). Use this page as your decision tree before jumping into the reference.

## Session cookies

* **Create** – `POST /api/auth/login` with `{ email, password, remember }`. When `remember` is `true`, a long-lived JWT is written to the `token` cookie. Otherwise the cookie lasts for the current browser session.
* **Check status** – `GET /api/auth` returns `status` plus the decoded JWT payload when signed in. Responses include `email_not_verified` and `2fa_required` states so you can prompt users accordingly.
* **Invalidate** – `GET /api/auth/logout` wipes the cookie.

## Email verification workflow

Some endpoints call `auth({ requireEmailVerification: true })`, which means unverified accounts will be rejected with HTTP 400. Use the following flow:

1. `POST /api/auth/verify/request` while signed in. Optionally include `returnUrl` to control where the CTA in the email sends users.
2. Users receive a JWT-backed link. Send the `token` to `POST /api/auth/verify/submit`.
3. On success, the API replies with `{ status: "ok", token }` and refreshes the `token` cookie.

## Password reset workflow

1. `POST /api/auth/reset/request` with `{ email, returnUrl? }`. Browsary emails a short-lived JWT.
2. `POST /api/auth/reset/submit` with `{ token, password, confirmPassword }`. The response mirrors the login response and refreshes the cookie.

## Two-factor authentication

All 2FA endpoints require an email-verified session.

| Endpoint                            | Purpose                                                                                              |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `POST /api/auth/2fa/enable/request` | Returns `{ status: "2fa_setup", url, secret }`. `url` is a TOTP URI you can encode as a QR code.     |
| `POST /api/auth/2fa/enable/submit`  | Confirms the authenticator by sending `{ token }` (the current TOTP). Response refreshes the cookie. |
| `POST /api/auth/2fa/verify`         | Called after login when the API reported `2fa_required`.                                             |
| `POST /api/auth/2fa/reset`          | Revokes the previous secret after the user proves ownership with the current TOTP code.              |

## API keys

* **Endpoints** – CRUD lives under `/api/api-keys` and `/api/api-keys/{id}`.
* **Delivery** – send keys via `x-api-key` or `Authorization: ApiKey <value>`. `Authorization: Bearer <value>` also works if your tooling only supports bearer schemes.
* **Scopes** – `accessType` controls what the key can see:
  * `full`: inherits the owner’s permissions.
  * `projects`: allow list of project IDs or slugs provided via `projectIds`.
  * `custom`: supply explicit permission strings (e.g. `marketing.pipelines.read`).
* **Lifecycle** – the API only shows the full `secret` on creation; subsequent reads expose metadata plus the prefix.

Remember that the project middleware re-evaluates permissions on every call. If you revoke a key, its future project requests fail automatically.

## External provider linking

OpenID Connect providers defined in `OPENID_PROVIDERS` unlock an external account linking flow:

1. `GET /api/auth/external/providers` lists supported providers (`google`, `github`, etc.).
2. Signed-in users call `GET /api/auth/external/{provider}/init`, which redirects them to the provider and stores PKCE state in cookies.
3. The provider calls back into `GET /api/auth/external/{provider}/redirect`. Browsary either links the provider to the signed-in user, logs in the existing linked account, or redirects to `/auth/external-register/<token>` to finish onboarding.
4. Use `GET`/`DELETE /api/auth/external/{provider}` to inspect or unlink accounts.

## Shared-secret integrations

Some system-level endpoints use dedicated middleware instead of user identity:

* **Coordinator** – all `/api/coordinator/<token>/*` routes require `token === process.env.COORDINATOR_TOKEN`.
* **External sessions** – `/api/external-session` and `/api/external-session/{id}/capture` require `Authorization: Bearer <EXTERNAL_TOKEN>` or a `?token=` query string.

Treat these secrets like infrastructure credentials—rotate them when compromised and never embed them in public clients.
