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

# Authentication and users

> First-administrator setup, invitations, local accounts, and runtime OIDC single sign-on.

r5d.chat supports local password accounts and an optional OIDC provider that
administrators configure at runtime, without a redeploy.

## First-administrator setup

A fresh installation has no users. The first successful setup request creates
the administrator and permanently closes public setup.

<Warning>
  Between exposing the installation and claiming it, anyone who reaches the URL
  can become the administrator. Always set `SETUP_CLAIM_TOKEN` before making an
  unclaimed installation reachable.
</Warning>

Setup requires a name, an email, a password of at least 12 characters containing
a letter and a number, and the claim token when one is configured.

Check the current state at any time:

```bash theme={null}
curl -fsS https://chat.example.com/api/setup
```

```json theme={null}
{ "required": false, "claimRequired": true }
```

`required: false` means the installation is claimed. The whole operation is a
single transaction, so concurrent attempts cannot produce two administrators.

## Invitations and local accounts

Administrators manage users from the admin area.

<Steps>
  <Step title="Create an invitation">
    Generates a single-use link for a new account.
  </Step>

  <Step title="Or create the account directly">
    Administrators can create an account with a temporary password and hand it
    over through a secure channel.
  </Step>

  <Step title="Manage roles and access">
    Promote users to administrator or disable accounts that should lose access.
  </Step>
</Steps>

<Tip>
  Keep at least one local administrator account even after enabling SSO. If the
  identity provider becomes unreachable or misconfigured, local login is the
  recovery path.
</Tip>

## OIDC single sign-on

Configure any standards-compliant OIDC provider at runtime from the admin
settings.

<ResponseField name="Provider key" type="string" required>
  Lowercase identifier used in callback URLs, matching `^[a-z0-9][a-z0-9-]{1,38}$`.
</ResponseField>

<ResponseField name="Label" type="string" required>
  Button text on the login page, for example "Sign in with Okta".
</ResponseField>

<ResponseField name="Issuer" type="string" required>
  The issuer URL, such as `https://login.example.com`.
</ResponseField>

<ResponseField name="Discovery URL" type="string">
  Optional explicit `.well-known/openid-configuration` URL when it is not at the
  standard location.
</ResponseField>

<ResponseField name="Client ID" type="string" required>
  OAuth client identifier from your provider.
</ResponseField>

<ResponseField name="Client secret" type="string" required>
  OAuth client secret. Encrypted with `SETTINGS_ENCRYPTION_KEY`.
</ResponseField>

<ResponseField name="Scopes" type="string" default="openid profile email">
  Space-separated scopes to request.
</ResponseField>

<ResponseField name="Auto-provision" type="boolean" default="false">
  Create an account automatically on first successful sign-in. Leave this off to
  require an invitation first.
</ResponseField>

<ResponseField name="Link by email" type="boolean" default="false">
  Link an SSO identity to an existing local account with the same email address.

  <Warning>
    Only enable this when the identity provider verifies email ownership.
    Otherwise a user who controls an unverified address at the IdP could take
    over an existing account.
  </Warning>
</ResponseField>

<ResponseField name="Allowed domains" type="array" default="[]">
  Restrict sign-in to specific email domains. Up to 50 entries. Recommended for
  any provider with a broad user base.
</ResponseField>

### Set it up

<Steps>
  <Step title="Register the application at your provider">
    Set the redirect URI to:

    ```
    https://chat.example.com/api/auth/oauth2/callback/<provider-key>
    ```

    `<provider-key>` is the provider key you configure below, and the host must
    match `publicUrl` exactly.
  </Step>

  <Step title="Enter the configuration">
    Fill in issuer, client ID, client secret, and scopes in the admin settings.
  </Step>

  <Step title="Test before enabling">
    Use the built-in test action, which validates discovery and the client
    credentials against the real provider.
  </Step>

  <Step title="Enable and verify">
    Enable the provider, then sign in from a private browser window to confirm
    the full round trip.
  </Step>
</Steps>

## Sessions

Sessions are cookie-based and signed with `BETTER_AUTH_SECRET`. Cookies are
scoped to the `publicUrl` host, which is why a mismatch between `publicUrl` and
the browser's address produces a login loop where sign-in appears to succeed but
the session is never recognized.

Rotating `BETTER_AUTH_SECRET` signs every user out.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Setup page reappears after creating an account">
    The transaction did not complete. Check control-plane logs for a database
    error and confirm `/api/setup` still reports `required: true`.
  </Accordion>

  <Accordion title="Login succeeds then bounces back to the login page">
    `publicUrl` does not match the browser URL, so the session cookie is rejected.
    Align `publicUrl`, `ingress.host`, and your DNS record.
  </Accordion>

  <Accordion title="OIDC returns redirect_uri_mismatch">
    The redirect URI registered at the provider differs from
    `https://<publicUrl-host>/api/auth/oauth2/callback/<provider-key>`. They must
    match exactly, including scheme and trailing path.
  </Accordion>

  <Accordion title="SSO users cannot sign in at all">
    With auto-provision disabled, an account must exist first. Either invite the
    user or enable auto-provision with an allowed-domain restriction.
  </Accordion>

  <Accordion title="OIDC config unreadable after a restore">
    The client secret is encrypted with `SETTINGS_ENCRYPTION_KEY`. Restore the
    original key or re-enter the OIDC configuration.
  </Accordion>
</AccordionGroup>
