# Authentication & identity

> Auth collections, passwords, OAuth, API tokens, and RBAC roles.

_Updated: 2026-06-10_

Authentication is built in. You declare which collections are sign-in capable, and
Railbase mounts the endpoints, hashes passwords, issues tokens, and enforces your
[access rules](schema).

## Auth collections

The core guarantees a built-in **`_users`** auth collection — end users sign up
and sign in against it with no schema work on your part. Add further auth
collections in the schema when you need separate identity pools:

```go
var Staff = s.AuthCollection("staff")   // injects email, password_hash, verified, …
func init() { s.Register(Staff) }
```

You can have several (`_users`, `staff`, `customers`) — each has its own sign-in
endpoints and an isolated email namespace. Operator/admin accounts (created with
`railbase admin create`) are separate from these app auth collections. See the
`_users` note in [Defining your schema](schema) before naming one `users`.

## Endpoints

Each auth collection gets, under `/api/collections/{name}/`:

```text
POST auth-signup              POST auth-with-password
POST auth-refresh             POST auth-logout
POST request-verification     POST confirm-verification
POST request-password-reset   POST confirm-password-reset
POST request-otp              POST auth-with-otp
GET  auth-with-oauth2/{provider}    + /callback
```

Plus TOTP, WebAuthn, and (where configured) LDAP/SAML. The signed-in identity is
at `GET /api/auth/me`. Responses carry `{ token, record }`.

## OAuth providers

Configure providers with environment variables — Google, GitHub, Apple, Microsoft
are built in:

```ini
RAILBASE_OAUTH_GOOGLE_CLIENT_ID=…
RAILBASE_OAUTH_GOOGLE_CLIENT_SECRET=…
RAILBASE_OAUTH_GITHUB_CLIENT_ID=…
RAILBASE_OAUTH_GITHUB_CLIENT_SECRET=…
```

## API tokens

For server-to-server access, mint long-lived bearer tokens:

```bash
railbase auth token create --owner <user-uuid> --collection _users \
  --name "ci-bot" --ttl 720h
railbase auth token list   [--owner <uuid>] [--all]
railbase auth token rotate <id> [--ttl 720h]
railbase auth token revoke <id>
```

`--collection` is the owner's **auth collection** and defaults to the built-in
`_users` — a token minted against a non-existent collection authenticates but
can't load its owner.

> [!IMPORTANT]
> The raw token is shown **once**, on create/rotate, and can't be recovered. Copy
> it then; if you lose it, rotate.

## Roles & permissions (RBAC)

Authorization is role-based, in two scopes — **site** (global) and **tenant**.
Manage roles from the CLI:

```bash
railbase role create site editor --desc "Can edit content"
railbase role grant  site editor posts.update
railbase role assign _users/<user-id> site editor
railbase role list-for _users/<user-id>
```

A subject is `<auth-collection>/<record-id>` — `_users/<id>` for app users (the
built-in collection), `_admins/<id>` for operator accounts.

The `system_admin` site role is immutable. In the [plugin model](building-plugins),
plugins **declare their own roles** at install time — the core doesn't hardcode
them, which is what makes per-seat billing by role work. See
[Licensing & seats](licensing-and-seats).
