# Authentication (/platform/self-hosting/authentication)

Configure the deployment's public origin and shared session secret before choosing login providers or restricting registration.

## Required configuration \[#required-configuration]

```text
BETTER_AUTH_SECRET=<openssl rand -hex 32>
BETTER_AUTH_URL=https://sim.yourdomain.com
NEXT_PUBLIC_APP_URL=https://sim.yourdomain.com
```

Replace the secret placeholder with the output of `openssl rand -hex 32`. Use your exact public origin, including scheme, with no trailing slash. Production Compose derives `BETTER_AUTH_URL` from `NEXT_PUBLIC_APP_URL`; see [Docker](/platform/self-hosting/docker).

Warning:

The app and realtime services must use the same `BETTER_AUTH_SECRET`. They share database sessions; a mismatch prevents authenticated socket connections. An incorrect public origin can cause rejected sign-in or redirect loops.

If the deployment serves additional origins, list them explicitly:

```bash
TRUSTED_ORIGINS=https://www.example.com,https://app.example.com
```

## Email and password \[#email-and-password]

Email/password sign-in and signup are enabled by default. To require email verification:

```bash
EMAIL_VERIFICATION_ENABLED=true
```

Verification is enforced only when a mail provider is configured. Test [email delivery](/platform/self-hosting/email) before requiring verification: a configured provider that cannot deliver still prevents new accounts from completing verification. Without a provider, verification is not enforced and invitations and password-reset mail are not delivered.

## Social login \[#social-login]

These providers sign members in to Sim itself. Integration account connections use separate callback paths.

| Provider | Variables | Login callback |
| - | - | - |
| Google | `GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET` | `https://<host>/api/auth/callback/google` |
| GitHub | `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` | `https://<host>/api/auth/callback/github` |
| Microsoft | `MICROSOFT_CLIENT_ID` / `MICROSOFT_CLIENT_SECRET` | `https://<host>/api/auth/callback/microsoft` |

Set both credentials to make a provider available on the login page. Microsoft is registered only when both values are present.

To keep credentials for integrations while disabling the corresponding login method:

```bash
DISABLE_GOOGLE_AUTH=true
DISABLE_GITHUB_AUTH=true
DISABLE_MICROSOFT_AUTH=true
```

Google and Microsoft share their client credentials with integrations. Register their login callback alongside the integration callbacks on the same client; see [Integrations and OAuth](/platform/self-hosting/integrations-oauth).

## Control registration and sign-in \[#controlling-who-can-sign-up]

| Variable | Effect |
| - | - |
| `DISABLE_REGISTRATION=true` | Blocks new email/password, email OTP, and social accounts. Existing accounts can sign in, including to accept workspace invitations. SSO registration is unaffected. |
| `DISABLE_EMAIL_SIGNUP=true` | Blocks new email/password and email OTP registrations. Existing accounts can still sign in through those methods. |
| `EMAIL_PASSWORD_SIGNUP_ENABLED=false` | Disables email/password and email OTP sign-in and signup, including for existing accounts. |
| `ALLOWED_LOGIN_DOMAINS` | Comma-separated email domain allowlist, such as `acme.com,acme.co.uk`. Applies to email/password and email OTP sign-in as well as email signup. |
| `ALLOWED_LOGIN_EMAILS` | Comma-separated address allowlist. An address or its domain may satisfy the allowlists. |
| `BLOCKED_SIGNUP_DOMAINS` | Comma-separated blocked domains. Blocks signup, sign-in, and executions for addresses in those domains, including subdomains. |
| `BLOCKED_EMAILS` | Comma-separated banned addresses. Blocks signup, sign-in, and executions. |
| `SIGNUP_MX_VALIDATION_ENABLED=true` | Checks email/password signup for a domain with no MX record or a blocked mail backend. |
| `BLOCKED_EMAIL_MX_HOSTS` | MX-host substrings to reject when MX validation is enabled. |

Warning:

Email allowlists do not filter first-time Google, GitHub, or Microsoft sign-in. To restrict social access, disable login providers you have not vetted or restrict membership through your identity provider and use SSO. MX validation applies only to email/password signup, not sign-in or email OTP. Registration-disabled and blocked-domain/address controls also cover social accounts.

For example, an installation using SSO while allowing existing company email accounts to sign in can set:

```bash
ALLOWED_LOGIN_DOMAINS=acme.com
DISABLE_EMAIL_SIGNUP=true
SSO_ENABLED=true
NEXT_PUBLIC_SSO_ENABLED=true
```

This does not restrict enabled social providers to `acme.com`. Configure or disable those login methods separately.

## SSO (SAML and OIDC) \[#sso-saml-and-oidc]

For a standard billing-disabled self-hosted deployment, enable the enterprise suite:

```bash
ENTERPRISE_ENABLED=true
NEXT_PUBLIC_ENTERPRISE_ENABLED=true
```

Or enable SSO alone:

```bash
SSO_ENABLED=true
NEXT_PUBLIC_SSO_ENABLED=true
```

Set both the server flag and its UI counterpart. Register providers under **Settings → Organization → Single sign-on**. A provider can belong to an organization or be registered without one.

Most other enterprise features read settings from the organization that owns a workspace. Set `INSTANCE_ORG_NAME` to place new members in one organization, or provision organizations through the Admin API. See [SSO](/platform/enterprise/sso) and [Self-hosted enterprise features](/platform/enterprise/self-hosted) for provider setup, organization patterns, and billing-enabled behavior.

## Behind a load balancer \[#behind-a-load-balancer]

Tell Better Auth which forwarding hops to trust when resolving client IPs:

```bash
AUTH_TRUSTED_PROXIES=10.0.0.0/24,192.0.2.10
```

Use your proxy addresses or CIDRs. Better Auth reads `X-Forwarded-For` from right to left, skips trusted proxies, and uses the first untrusted address for session records and IP checks. A range that also trusts client traffic defeats this boundary. See [Security](/platform/self-hosting/security).

## Sign in with Sim \[#sign-in-with-sim]

Sim also acts as an OAuth 2.0 authorization server, using authorization code with PKCE. It supports API authorization rather than OpenID Connect identity: it does not issue ID tokens. See [CLI authentication](/cli/authentication).

Access tokens are opaque and last one hour. Refresh tokens rotate on use, and each login has a fixed thirty-day lifetime that refresh does not extend. Validation checks current grants: revoking access under **Settings → General → Authorized apps** stops the app on its next request. Scheduled token cleanup runs independently of sign-in activity.

`DISABLE_AUTH=true` disables OAuth sign-in and discovery because these require a real member session. Older servers without OAuth support return `404` from `/.well-known/oauth-authorization-server`; the CLI can fall back to pairing-code login.

### Client registration \[#registering-an-app]

MCP clients can use the public registration endpoint at `/api/auth/oauth2/register`. It accepts reviewed callback formats, requires PKCE, and accepts at most 10 redirect URIs in a JSON body capped at 32 KiB. Its per-IP bucket holds 20 registration tokens and refills 20 each minute. Registration grants no resource access by itself. Members must consent, and each MCP grant is narrowed to the API or Search resource it addresses.

The available scopes are `offline_access`, `api:read`, `api:write`, and `search:read`. API and Search resource scope families remain distinct. Public registration permits HTTPS callbacks, loopback HTTP callbacks, and the explicitly supported Cursor native callback; it does not accept arbitrary custom URI schemes.

Operators create first-party and confidential clients. Both `db:migrate` and the development `db:push` command install OAuth lifecycle triggers and register the Sim CLI, preserving existing grants and client customizations on repeat runs. From a source checkout, register another app with:

```bash
DATABASE_URL=… \
BETTER_AUTH_SECRET=… \
OAUTH_CLIENT_ID=my-app \
OAUTH_CLIENT_NAME="My App" \
OAUTH_REDIRECT_URIS=https://my-app.example/callback \
OAUTH_SCOPES=api:read \
bun run apps/sim/scripts/create-oauth-client.ts
```

Add `OAUTH_CLIENT_PUBLIC=true` for a native or CLI app that cannot keep a secret. Confidential clients use `client_secret_basic`; the command prints the authentication method and prints the client secret once. The secret cannot be read back.

Operator-registered redirect URIs must use HTTPS or HTTP on a loopback address. They match exactly, except that loopback callbacks may use any port.

### Authorization and upgrades \[#authorization-and-upgrades]

Organization admins can restrict **OAuth App Access** under **Credentials & Access** in [permission groups](/platform/enterprise/access-control). Workspace requests use the group governing that workspace; authorization, issuance, refresh, and account-level billing/audit reads use the organization's default group. **CLI Access** also applies to the Sim CLI. Members can still inspect and revoke existing grants when OAuth app access is restricted.

Apply database migrations before a new app version. When upgrading from a version without the OAuth token-family lifecycle, drain older app instances before accepting OAuth traffic so all instances enforce the same refresh and revocation rules.

## Disable authentication \[#disabling-authentication-entirely]

```bash
DISABLE_AUTH=true
```

Requests use a shared anonymous session.

Note:

Anyone who can reach the instance can act through that session. Use this only for a single-user installation on a private network; do not expose it through an internet-facing ingress.

## Other controls \[#other-controls]

| Variable | Effect |
| - | - |
| `DISABLE_INVITATIONS=true` / `NEXT_PUBLIC_DISABLE_INVITATIONS=true` | Disable workspace invitations globally. |
| `DISABLE_PUBLIC_API=true` / `NEXT_PUBLIC_DISABLE_PUBLIC_API=true` | Disable the public API globally. |
| `ADMIN_API_KEY` | Enables Admin API GitOps operations and organization provisioning. |

Set both server and `NEXT_PUBLIC_` flags where a pair is listed. The server flag enforces the restriction; its counterpart controls the UI.

## Verify authentication \[#verify-authentication]

Sign out and sign back in at the public origin, then open a workflow in two browser windows and confirm edits propagate. Test each enabled login method. If verification is required, create a test account and confirm the message arrives and the verification succeeds. Use [Verify your install](/platform/self-hosting/verify) for deployment checks.

## Related docs \[#related-docs]

- [Email](/platform/self-hosting/email)
- [Integrations and OAuth](/platform/self-hosting/integrations-oauth)
- [Verified domains](/platform/enterprise/verified-domains)
