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

# Authentication

> httpOnly cookie-based JWT session authentication for browsers, EHR integrations, and server-to-server use.

<Warning>
  Denialbase does **not** issue Bearer tokens for browser clients. Session state lives in an httpOnly cookie that is not accessible to JavaScript. This is a deliberate security choice — see [Authentication & access control](/trust/authentication) for the rationale.
</Warning>

## Session flow (interactive)

<Steps>
  <Step title="POST /api/v1/auth/session">
    With `{ email, password }` body. If 2FA is enabled (it is, for all PHI accounts), the server responds with a `402 Two-Factor Required` including a short-lived continuation token.
  </Step>

  <Step title="POST /api/v1/auth/session/2fa">
    With `{ continuation_token, code }` or the passkey assertion. On success, the server sets an `httpOnly` session cookie.
  </Step>

  <Step title="Subsequent requests">
    Include the cookie automatically. Browser requests need no additional headers.
  </Step>

  <Step title="POST /api/v1/auth/session/logout">
    Server revokes the session and clears the cookie.
  </Step>
</Steps>

## Example

<CodeGroup>
  ```bash cURL theme={null}
  # 1. Sign in
  curl -c cookies.txt -X POST https://api.denialbase.com/api/v1/auth/session \
    -H "Content-Type: application/json" \
    -d '{"email":"you@example.com","password":"…"}'

  # 2. Complete 2FA
  curl -b cookies.txt -c cookies.txt -X POST https://api.denialbase.com/api/v1/auth/session/2fa \
    -H "Content-Type: application/json" \
    -d '{"code":"123456"}'

  # 3. Call a protected endpoint
  curl -b cookies.txt https://api.denialbase.com/api/v1/denials
  ```

  ```javascript fetch (browser) theme={null}
  // Browser automatically stores + sends the httpOnly cookie.
  await fetch("https://api.denialbase.com/api/v1/auth/session", {
    method: "POST",
    credentials: "include",           // IMPORTANT
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ email, password }),
  });

  // Subsequent requests:
  await fetch("https://api.denialbase.com/api/v1/denials", {
    credentials: "include",
  });
  ```
</CodeGroup>

## CSRF protection

Because authentication is cookie-based, state-changing requests require a CSRF token:

* The server sets a `csrf_token` value in a readable cookie on login.
* Clients send this value as `X-CSRF-Token` on every `POST`, `PUT`, `PATCH`, `DELETE`.
* Safe methods (`GET`, `HEAD`, `OPTIONS`) don't need the token.

## Other factors

<CardGroup cols={2}>
  <Card title="Passkeys (WebAuthn)" icon="fingerprint">
    For passkey sign-in, the 2FA step is replaced by a WebAuthn assertion. See the full flow in the API reference.
  </Card>

  <Card title="Magic links" icon="envelope">
    `POST /api/v1/auth/magic_link` sends a one-time sign-in link. Link includes a short-TTL token that, when consumed, establishes the session.
  </Card>

  <Card title="Google OAuth 2.1" icon="google">
    `GET /api/v1/auth/oauth/google` redirects to Google; return callback establishes the session.
  </Card>

  <Card title="SAML SSO" icon="key">
    Enterprise SAML 2.0 via `POST /api/v1/auth/saml/<provider>`. See [SSO / SAML](/integrations/sso-saml).
  </Card>
</CardGroup>

## API tokens (server-to-server)

For non-browser use cases (EHR webhooks, server-side integrations), request a scoped API token:

<Steps>
  <Step title="Generate a token">
    **Settings → Developers → API tokens → New token**. Choose scopes (`documents:write`, `denials:read`, etc.) and an expiry.
  </Step>

  <Step title="Use the token">
    ```bash theme={null}
    curl -H "Authorization: Bearer dbs_live_…" \
      https://api.denialbase.com/api/v1/denials
    ```

    Tokens include their environment prefix (`dbs_live_` or `dbs_test_`) and a checksum suffix.
  </Step>

  <Step title="Rotate">
    Regenerate from the same settings page. Old tokens remain valid for a configurable grace window.
  </Step>
</Steps>

## Session lifecycle

| Control                                       | Default                             |
| --------------------------------------------- | ----------------------------------- |
| Idle timeout                                  | 30 minutes                          |
| Max session duration                          | 24 hours                            |
| Concurrent sessions                           | Unlimited (admin-configurable to 1) |
| 2FA required for re-auth on sensitive actions | Yes                                 |
