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

# Authentication and accounts

> Every request is authenticated. The first account on a fresh instance becomes the owner, and registration closes automatically afterwards.

Authentication is always on and cannot be disabled. The same image runs on `localhost` and on a public host, so a disable switch would be a setting somebody forgets to change on the day the instance becomes reachable.

## First run

A fresh installation redirects to registration. The account you create there becomes the owner.

The first account always bootstraps as owner regardless of `AUTH_ALLOW_REGISTRATION`, so a locked down deployment can still create its first user.

Set `AUTH_SECRET` before the first boot. The API refuses to start with fewer than 32 characters.

```bash theme={null}
openssl rand -hex 32
```

## Registration

`AUTH_ALLOW_REGISTRATION` defaults to `false`, which closes registration the moment the owner account exists. That is the right default for a single operator deployment.

Set it to `true` when more people need to sign themselves up. There is no invitation flow, so the choice is between closed and open.

## Sessions

A session is a JWT in an `httpOnly`, `SameSite=Lax` cookie named `asobeast_session`, signed with `AUTH_SECRET`.

| Setting              | Default | Effect                                                          |
| -------------------- | ------- | --------------------------------------------------------------- |
| `AUTH_SESSION_DAYS`  | `7`     | Cookie lifetime in days                                         |
| `AUTH_COOKIE_SECURE` | `false` | Must be `true` behind TLS so the cookie is sent only over HTTPS |

Because the browser talks only to the web origin and the proxy forwards the cookie, there is nothing cross site to configure. A JSON only API plus `SameSite=Lax` is the CSRF story.

Rotating `AUTH_SECRET` invalidates every existing session, so everyone is signed out. See [Rotate secrets](/operations/rotate-secrets).

## Rotate a password

Changing your password from the account menu bumps a session version, which signs out every other session while the one you are using keeps working. That is what you want after a laptop is lost.

The auth endpoints, including register, login, password change and token creation, are rate limited per client IP address.

## How is a request authorized?

Two guards run in order on every request.

| Guard              | Accepts                                     | Rejects with |
| ------------------ | ------------------------------------------- | ------------ |
| `AuthGuard`        | A session cookie or an `asob_` bearer token | `401`        |
| `EntitlementGuard` | An entitled account                         | `402`        |

A small set of routes is marked public, and account plus paywall routes stay reachable even for an unentitled account so an expired user can sign in and pay.

All users share the seeded default workspace. Every tenant owned row already carries `workspaceId`, so per user isolation is prepared, but team roles, invitations and multi workspace administration are not implemented.

## Entitlements and the premium seam

`BILLING_ENABLED` defaults to `false`, which means every account is entitled and nothing is gated.

Setting it to `true` turns on an entitlement check without wiring a payment provider. Registration stays open, each new account is stamped with a `TRIAL_DAYS` trial defaulting to 7, and an unentitled request answers `402` through the standard error envelope, which the web app catches and turns into the upgrade page.

The seam writes only `plan`, `planExpiresAt` and `billingCustomerId`. Setting `plan` to `premium` in the database restores access with no code change.

## Troubleshooting

* **You are signed out after a restart.** `AUTH_SECRET` changed. Sessions are signed with it.
* **You cannot register a second account.** Registration closed after the owner account. Set `AUTH_ALLOW_REGISTRATION=true`.
* **Sessions do not persist behind a proxy.** Check `AUTH_COOKIE_SECURE` against whether the browser reaches you over HTTPS. See [Hosting behind TLS and a reverse proxy](/security/hosting).

## Related

<CardGroup cols={2}>
  <Card title="Personal API tokens" icon="key-round" href="/security/api-tokens">
    Authenticate a script or an agent.
  </Card>

  <Card title="Hosting behind TLS and a reverse proxy" icon="shield" href="/security/hosting">
    The checklist before exposing an instance.
  </Card>
</CardGroup>
