Skip to main content
Version: 2.x (Latest)

Server Configuration (v2)

Authorizer v2 uses CLI flags only for configuration. Nothing is loaded from .env files or dashboard-managed env, and config is not persisted in the database or cache.

If you are migrating from v1, first skim the high-level Migration v1 to v2 guide and then use this page as a reference.


1. Core flags

./authorizer \
--env=production \
--http-port=8080 \
--host=0.0.0.0 \
--metrics-port=8081 \
--metrics-host=127.0.0.1 \
--log-level=info
  • --env: environment name (for example production, development).
  • --http-port: HTTP listen port (default 8080).
  • --host: bind address for the main HTTP server (default 0.0.0.0).
  • --metrics-port: port for the dedicated /metrics listener (default 8081; must differ from --http-port). Health probes stay on the HTTP port.
  • --metrics-host: bind address for that dedicated metrics listener only (default 127.0.0.1). The main app can listen on all interfaces while metrics stay on loopback. For Docker/Kubernetes scraping from another container/pod, set --metrics-host=0.0.0.0 and keep the metrics port on an internal network only (never on a public load balancer).
  • --log-level: one of debug, info, warn, error, fatal, panic.

2. Database and session store

Database

./authorizer \
--database-type=postgres \
--database-url="postgres://user:pass@host/db" \
--database-name=authorizer \
--database-host=db-host \
--database-port=5432

Key flags:

  • --database-type: postgres, mysql, planetscale, sqlite, sqlserver, mongodb, arangodb, yugabyte, mariadb, cassandradb, scylladb, couchbase, dynamodb, etc.
  • --database-url: connection string.
  • Optional per-driver flags (name, host, port, TLS certs, etc.) -- see the mapping table in Migration v1 to v2.

Session / cache

./authorizer \
--redis-url=redis://user:pass@redis-host:6379/0
  • --redis-url: Redis connection string used for session storage. If omitted, sessions are stored in memory (suitable only for dev / single-node setups).

3. OAuth / app behavior

These flags replace v1 env such as CLIENT_ID, CLIENT_SECRET, and app behavior toggles.

./authorizer \
--client-id=YOUR_CLIENT_ID \
--client-secret=YOUR_CLIENT_SECRET \
--admin-secret=your-admin-secret \
--allowed-origins=https://your-app.com,http://localhost:3000 \
--default-authorize-response-type=code \
--default-authorize-response-mode=query
  • --client-id (required): instance/client identifier.
  • --client-secret (required): secret used for token-related operations.
  • --admin-secret (required, non-empty): super-admin secret for admin operations. Breaking change as of April 2026: there is no default any more — empty causes the server to exit at startup. Pick any non-empty value; the strength of the secret is your responsibility. See Security Hardening.
  • --allowed-origins: comma-separated list of allowed origins (default *). A startup warning is logged when the value contains * — set an explicit allowlist for production. See CORS, CSRF and origin enforcement.
  • --trusted-proxies (default empty): comma-separated CIDRs of reverse proxies whose X-Forwarded-For should be honoured. Breaking change as of April 2026: defaults to none — operators behind a proxy must set this explicitly or rate limiting and audit logs will key on the proxy IP. See Trusted proxies.
  • --url (default empty): canonical/trusted base URL of this instance (e.g. https://auth.example.com). When set, it is the only source used to build verification/reset/magic-link email URLs, the JWT iss claim, and OIDC discovery URLs — the X-Authorizer-URL, X-Forwarded-Host, and Host request headers are ignored for that purpose. Leaving it empty keeps legacy header-based derivation. Recommended for production, especially behind a reverse proxy. See Trusted base URL.

Organization / UI:

./authorizer \
--organization-name="Your Company" \
--organization-logo="https://your-cdn/logo.png" \
--enable-login-page=true \
--enable-playground=false \
--enable-graphql-introspection=false
  • --enable-login-page: set to false to disable the built-in login UI.
  • --enable-playground: set to false to disable the GraphQL playground.
  • --enable-graphql-introspection: set to false in hardened environments.

4. Auth behavior and cookies

Roles and auth flows

./authorizer \
--roles=user,admin \
--default-roles=user \
--protected-roles=admin \
--enable-strong-password=true \
--enable-basic-authentication=true \
--enable-email-verification=true \
--enable-magic-link-login=true \
--enable-signup=true

These replace v1 flags such as DISABLE_BASIC_AUTHENTICATION, DISABLE_EMAIL_VERIFICATION, etc. See the Auth behavior mapping for exact correspondences.

Multi-factor authentication (MFA) & WebAuthn/passkeys

Breaking change: --enable-mfa, --enable-totp-login, --enable-email-otp, and --enable-sms-otp are removed. TOTP, email OTP, SMS OTP, and WebAuthn/passkey-as-MFA are now all on by default; opt out per method with the --disable-* flags below. --enforce-mfa also flipped its default from true to false — MFA is now optional and skippable unless you explicitly enforce it.

./authorizer \
--enforce-mfa=false \
--disable-mfa=false \
--disable-totp-login=false \
--disable-webauthn-mfa=false \
--disable-email-otp=false \
--disable-sms-otp=false
  • --enforce-mfa (default false): require every user to complete MFA enrollment before a token is issued (mfaGateBlockEnroll, never skippable). When false, users are offered MFA setup once and may skip it (skip_mfa_setup mutation); a user's own already-enrolled factor is always required to verify regardless of this flag.
  • --disable-mfa (default false): one-way global kill switch — forces MFA off entirely (TOTP/email-OTP/SMS-OTP unavailable, --enforce-mfa neutralized) regardless of the per-method flags below. Does not affect WebAuthn/passkey as a primary login method (only as an MFA factor).
  • --disable-totp-login (default false): disable TOTP authenticator-app MFA.
  • --disable-webauthn-mfa (default false): disable WebAuthn/passkey as an MFA factor. Does not affect WebAuthn/passkey as a primary, passwordless login method — that is always available and has no flag.
  • --disable-email-otp (default false): disable email-OTP MFA. Only takes effect when SMTP is configured (--smtp-*); otherwise email OTP is unavailable regardless of this flag.
  • --disable-sms-otp (default false): disable SMS-OTP MFA. Only takes effect when Twilio is configured (--twilio-*); otherwise SMS OTP is unavailable regardless of this flag.

Effective availability of each method is exposed on the public meta GraphQL query (is_totp_mfa_enabled, is_email_otp_mfa_enabled, is_sms_otp_mfa_enabled, is_webauthn_enabled, is_mfa_enforced) so frontends never have to reverse-engineer flag combinations. See MFA & Passkeys for the full behavior — withheld-token first-time setup, lockout, admin recovery, and the WebAuthn/passkey GraphQL operations.

Cookies

./authorizer \
--app-cookie-secure=true \
--admin-cookie-secure=true

Use true for HTTPS-only cookies in production.


5. JWT configuration

./authorizer \
--jwt-type=HS256 \
--jwt-secret=your-jwt-secret \
--jwt-role-claim=role

Or for asymmetric keys:

./authorizer \
--jwt-type=RS256 \
--jwt-private-key="$(cat /path/to/private.key)" \
--jwt-public-key="$(cat /path/to/public.key)"

Additional flags:

  • --custom-access-token-script: path/string for custom token augmentation logic (advanced use only).
  • --refresh-token-expires-in (default 2592000, 30 days): refresh-token lifetime in seconds. Previously hardcoded — now operator-configurable.

In v2, the _generate_jwt_keys mutation is deprecated and returns an error; configure keys only via flags.

Note on key rotation: --jwt-secret is also used to encrypt TOTP shared secrets at rest and to HMAC OTPs. Rotating it will lock out every user with an enrolled TOTP authenticator until they re-enrol. See OTP and TOTP at rest.


6. SMTP and SMS

SMTP

./authorizer \
--smtp-host=smtp.mailprovider.com \
--smtp-port=587 \
--smtp-username=user@example.com \
--smtp-password=strong-password \
--smtp-sender-email=auth@example.com \
--smtp-sender-name="Auth Team" \
--smtp-local-name=authorizer \
--smtp-skip-tls-verification=false

Twilio (SMS OTP)

./authorizer \
--twilio-account-sid=AC... \
--twilio-api-key=... \
--twilio-api-secret=... \
--twilio-sender=+123456789

7. Social / OAuth providers

Each provider uses its own set of flags:

./authorizer \
--google-client-id=... \
--google-client-secret=... \
--google-scopes="openid,email,profile" \
--github-client-id=... \
--github-client-secret=... \
--github-scopes="read:user,user:email"

Other supported providers follow the same pattern:

  • --facebook-client-id, --facebook-client-secret, --facebook-scopes
  • --microsoft-client-id, --microsoft-client-secret, --microsoft-tenant-id, --microsoft-scopes
  • --apple-client-id, --apple-client-secret, --apple-scopes
  • --linkedin-client-id, --linkedin-client-secret, --linkedin-scopes
  • --discord-client-id, --discord-client-secret, --discord-scopes
  • --twitter-client-id, --twitter-client-secret, --twitter-scopes
  • --twitch-client-id, --twitch-client-secret, --twitch-scopes
  • --roblox-client-id, --roblox-client-secret, --roblox-scopes

8. Rate limiting

./authorizer \
--rate-limit-rps=30 \
--rate-limit-burst=20 \
--rate-limit-fail-closed=false
  • --rate-limit-rps: maximum sustained requests per second per IP (default 30). Set to 0 to disable.
  • --rate-limit-burst: maximum burst size per IP (default 20).
  • --rate-limit-fail-closed: when true, a failing rate-limit backend returns 503 instead of allowing the request (default false, fail-open).

Rate limiting is always enabled by default. When --redis-url is set, limits are shared across replicas via Redis. See Rate Limiting for full details.


9. Admin and GraphQL security flags

New in v2:

./authorizer \
--disable-admin-header-auth=true \
--enable-graphql-introspection=false \
--graphql-max-complexity=300 \
--graphql-max-depth=15 \
--graphql-max-aliases=30 \
--graphql-max-body-bytes=1048576
  • --disable-admin-header-auth: when true, the server ignores X-Authorizer-Admin-Secret and only honors the secure admin cookie. Recommended for production.
  • --enable-graphql-introspection: disable in locked-down environments.
  • --graphql-max-complexity (default 300): max total complexity score per operation.
  • --graphql-max-depth (default 15): max selection-set nesting depth.
  • --graphql-max-aliases (default 30): max aliased fields per operation (defends against alias amplification).
  • --graphql-max-body-bytes (default 1048576, 1 MiB): max GraphQL request body size.

GET /graphql is no longer accepted — clients must POST. Rejections are counted in the authorizer_graphql_limit_rejections_total Prometheus metric, labelled by limit kind. See GraphQL hardening for details.

Authorization (FGA)

./authorizer \
--fga-store=postgres \
--fga-store-url="postgres://user:pass@host/db" \
--include-permissions-in-token=false \
--authorization-log-all-checks=false
  • --fga-store: backing store for the embedded OpenFGA engine — one of sqlite, postgres, mysql, or memory. Only needed when the main database is NoSQL (see paragraph below); for SQL main databases the engine reuses that database automatically.
  • --fga-store-url: connection string for the FGA store when --fga-store is set to a database driver.
  • --include-permissions-in-token (default false): when true, the access token's claims include the caller's flat (resource, scope) grant list. Useful for stateless downstream services that don't want to round-trip back to Authorizer per check.
  • --authorization-log-all-checks (default false): audit-log every CheckPermission call, not just denials. Diagnostic; expensive at scale.

Authorizer ships an embedded OpenFGA (ReBAC) engine. It is enabled by default when the main database is SQL-compatible (SQLite/Postgres/MySQL) and reuses that database. For NoSQL main databases (MongoDB, DynamoDB, …) it is off unless you set --fga-store (one of sqlite/postgres/mysql/memory) and --fga-store-url. Checks fail closed. See Authorization (FGA).


9. Security headers

./authorizer \
--enable-hsts=true \
--disable-csp=false
  • --enable-hsts (default false): emit Strict-Transport-Security. Only enable behind TLS — turning HSTS on without TLS will lock browsers out for a year.
  • --disable-csp (default false): disable the default Content-Security-Policy header. CSP is on by default.

The defaults are conservative and documented at Security response headers.


10. Full security reference

See the dedicated Security Hardening page for:

  • The complete list of security CLI flags introduced in April 2026
  • Trusted-proxy configuration for various deployment topologies
  • CSRF, CORS, OAuth flow, and webhook SSRF protections (all automatic)
  • OTP and TOTP at-rest hardening, including the rolling-deploy note for multi-replica clusters
  • Login error normalization and user-enumeration defences
  • Multi-factor authentication (MFA) behavior, lockout, admin recovery, and WebAuthn/passkey ceremonies

11. Discovering all flags

To list all available flags and their defaults, run:

./authorizer --help

For a v1 to v2 mapping table, see Configuration Mapping.