Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration

Overview

The oauth2-passkey library uses environment variables for configuration. This approach provides flexibility for different deployment scenarios and keeps sensitive credentials out of source code.

Configuration is loaded at application startup. All variables can be set via:

  • Environment variables directly
  • A .env file in the project root (using the dotenvy crate)

Required Variables

These variables must be set for the library to function.

ORIGIN

The base URL of your application. This is used for:

  • Constructing OAuth2 callback URLs
  • Setting the WebAuthn Relying Party ID
  • Validating request origins
ORIGIN='https://your-domain.example.com'

Important: No trailing slash.

OAUTH2_GOOGLE_CLIENT_ID

Your Google OAuth2 client ID obtained from the Google Cloud Console.

OAUTH2_GOOGLE_CLIENT_ID='your-client-id.apps.googleusercontent.com'

OAUTH2_GOOGLE_CLIENT_SECRET

Your Google OAuth2 client secret obtained from the Google Cloud Console.

OAUTH2_GOOGLE_CLIENT_SECRET='your-client-secret'

OAUTH2_ISSUER_URL

The OIDC (OpenID Connect) issuer URL. The library uses OIDC Discovery to automatically fetch endpoint configurations from the .well-known/openid-configuration URL.

OAUTH2_ISSUER_URL='https://accounts.google.com'

For Google authentication, use https://accounts.google.com.

Database Configuration

GENERIC_DATA_STORE_TYPE

Specifies the database backend for persistent storage.

ValueDescription
sqliteSQLite database (development/testing)
postgresPostgreSQL database (production)
GENERIC_DATA_STORE_TYPE=postgres

GENERIC_DATA_STORE_URL

Connection URL for the database.

PostgreSQL format:

GENERIC_DATA_STORE_URL='postgresql://user:password@host:port/database'

SQLite formats:

# File-based SQLite
GENERIC_DATA_STORE_URL='sqlite:/path/to/database.db'
GENERIC_DATA_STORE_URL='sqlite:./db/sqlite/data/data.db'

# In-memory SQLite (useful for testing)
GENERIC_DATA_STORE_URL='sqlite:file:memdb1?mode=memory&cache=shared'
GENERIC_DATA_STORE_URL=':memory:'

Cache Configuration

GENERIC_CACHE_STORE_TYPE

Specifies the cache backend for temporary data (sessions, challenges, CSRF tokens).

ValueDescription
memoryIn-memory cache (development/single instance)
redisRedis cache (production/multi-instance)
GENERIC_CACHE_STORE_TYPE=redis

GENERIC_CACHE_STORE_URL

Connection URL for Redis (only required when using Redis cache).

GENERIC_CACHE_STORE_URL='redis://localhost:6379'

Optional Variables

Route Configuration

O2P_ROUTE_PREFIX

Main route prefix for all authentication endpoints.

  • Default: /o2p
  • Endpoints affected: OAuth2, passkey, login, logout, summary pages
O2P_ROUTE_PREFIX='/o2p'

O2P_LOGIN_URL

URL of the login page. Used by middleware and the AuthUser extractor to redirect unauthenticated users.

  • Default: /o2p/user/login
  • Set this to override the default login page URL
  • Required when the login-ui feature is disabled
O2P_LOGIN_URL='/o2p/user/login'

O2P_DEFAULT_REDIRECT

Default redirect URL for authenticated-user flows. Used when:

  • Authenticated users visit the login page (bounce to app root)

  • Logout redirect target in templates

  • Default: /

O2P_DEFAULT_REDIRECT='/'

O2P_ACCOUNT_URL

URL path for the user account management page.

  • Default: /o2p/user/account
O2P_ACCOUNT_URL='/o2p/user/account'

O2P_RESPOND_WITH_X_CSRF_TOKEN

Controls whether the X-CSRF-Token header is included in responses.

  • Default: true
  • Values: true, false
O2P_RESPOND_WITH_X_CSRF_TOKEN=false

Demo Mode

O2P_DEMO_MODE

Enable demo mode for public demo deployments.

  • Default: false
  • Values: true, false
O2P_DEMO_MODE=true

When enabled:

  • All new users automatically receive admin privileges
  • Admin pages mask other users’ sensitive data (email, name, IDs, IP addresses)
  • A placeholder user is created at seq=1 so no real user gets first-user admin treatment

WebAuthn Configuration

WEBAUTHN_ADDITIONAL_ORIGINS

Additional origins allowed to use WebAuthn credentials (for multi-domain support).

WEBAUTHN_ADDITIONAL_ORIGINS='https://example.com'

Important: No trailing slash in URLs.

PASSKEY_RP_NAME

The Relying Party name displayed to users during passkey registration.

  • Default: Same as ORIGIN
PASSKEY_RP_NAME='My Application'

PASSKEY_TIMEOUT

Client-side timeout (in seconds) sent to the authenticator.

  • Default: 60
PASSKEY_TIMEOUT=60

PASSKEY_CHALLENGE_TIMEOUT

Server-side timeout (in seconds) for challenge validity.

  • Default: 60
PASSKEY_CHALLENGE_TIMEOUT=60

PASSKEY_AUTHENTICATOR_ATTACHMENT

Specifies which type of authenticator to allow.

ValueDescription
platformBuilt-in authenticators (Touch ID, Face ID, Windows Hello, password managers)
cross-platformRemovable authenticators (YubiKey, security keys)
NoneAllow any type
  • Default: platform
PASSKEY_AUTHENTICATOR_ATTACHMENT='platform'

PASSKEY_RESIDENT_KEY

Controls resident key (discoverable credential) requirement.

ValueDescription
requiredCredential must be discoverable
preferredPrefer discoverable, but allow non-discoverable
discouragedPrefer non-discoverable credentials
  • Default: required
PASSKEY_RESIDENT_KEY='required'

PASSKEY_REQUIRE_RESIDENT_KEY

Whether to require resident key support.

  • Default: true
  • Values: true, false
PASSKEY_REQUIRE_RESIDENT_KEY=true

PASSKEY_USER_VERIFICATION

User verification requirement during authentication.

ValueDescription
requiredAlways require user verification (PIN, biometric)
preferredRequest verification if available
discouragedSkip verification if possible
  • Default: discouraged
PASSKEY_USER_VERIFICATION='discouraged'

PASSKEY_USER_HANDLE_UNIQUE_FOR_EVERY_CREDENTIAL

Controls user handle generation strategy.

ValueBehavior
falseUse single user_handle for all credentials for a user (limits to one credential per user per site)
trueGenerate unique user_handle per credential (allows multiple credentials per user per site)
  • Default: false
PASSKEY_USER_HANDLE_UNIQUE_FOR_EVERY_CREDENTIAL=false

Note: Password managers typically allow only one credential per user identifier. Set to true if users need multiple passkeys.

OAuth2 Advanced Configuration

OAUTH2_AUTH_URL

Override the authorization endpoint (normally discovered from issuer).

OAUTH2_AUTH_URL='https://accounts.google.com/o/oauth2/v2/auth'

OAUTH2_TOKEN_URL

Override the token endpoint (normally discovered from issuer).

OAUTH2_TOKEN_URL='https://oauth2.googleapis.com/token'

OAUTH2_SCOPE

OAuth2 scopes to request.

  • Default: openid+email+profile
OAUTH2_SCOPE='openid+email+profile'

OAUTH2_RESPONSE_MODE

How the authorization response is returned.

ValueDescription
form_postResponse via POST to callback (uses SameSite=None for CSRF cookies)
queryResponse via query parameters (uses SameSite=Lax for CSRF cookies)
  • Default: form_post
OAUTH2_RESPONSE_MODE='form_post'

OAUTH2_RESPONSE_TYPE

OAuth2 response type.

  • Default: code
  • Note: Only the authorization code flow is supported.
OAUTH2_RESPONSE_TYPE='code'

Name of the CSRF protection cookie for OAuth2 flows.

  • Default: __Host-CsrfId
OAUTH2_CSRF_COOKIE_NAME='__Host-CsrfId'

Maximum age (in seconds) for the CSRF cookie.

  • Default: 60
OAUTH2_CSRF_COOKIE_MAX_AGE=60

Name of the session cookie.

  • Default: __Host-SessionId
SESSION_COOKIE_NAME='__Host-SessionId'

Maximum age (in seconds) for the session cookie.

  • Default: 600
SESSION_COOKIE_MAX_AGE=600

SESSION_CONFLICT_POLICY

Controls behavior when a user logs in while already having active sessions.

ValueDescription
allowPermit multiple concurrent sessions (default)
replaceInvalidate all existing sessions, create a new one
rejectDeny login if an active session already exists
  • Default: allow
SESSION_CONFLICT_POLICY=allow

See Session Conflict Policy for detailed documentation.

User Field Mapping

These settings control how user fields are mapped between authentication providers and the internal user model.

OAUTH2_USER_ACCOUNT_FIELD

OAuth2 claim to use for User.account.

  • Default: email
OAUTH2_USER_ACCOUNT_FIELD='email'

OAUTH2_USER_LABEL_FIELD

OAuth2 claim to use for User.label.

  • Default: name
OAUTH2_USER_LABEL_FIELD='name'

PASSKEY_USER_ACCOUNT_FIELD

Passkey field to use for User.account.

  • Default: name
PASSKEY_USER_ACCOUNT_FIELD='name'

PASSKEY_USER_LABEL_FIELD

Passkey field to use for User.label.

  • Default: display_name
PASSKEY_USER_LABEL_FIELD='display_name'

Security Configuration

AUTH_SERVER_SECRET

Secret key used for token signing.

  • Default: default_secret_key_change_in_production
AUTH_SERVER_SECRET='your-secret-key-here'

Warning: Always change this value in production environments. Use a cryptographically secure random string.

Database Table Configuration

DB_TABLE_PREFIX

Prefix for all database tables created by the library.

  • Default: o2p_
DB_TABLE_PREFIX='o2p_'

DB_TABLE_USERS

Custom name for the users table.

  • Default: {prefix}users (e.g., o2p_users)
DB_TABLE_USERS='o2p_users'

DB_TABLE_PASSKEY_CREDENTIALS

Custom name for the passkey credentials table.

  • Default: {prefix}passkey_credentials (e.g., o2p_passkey_credentials)
DB_TABLE_PASSKEY_CREDENTIALS='o2p_passkey_credentials'

DB_TABLE_OAUTH2_ACCOUNTS

Custom name for the OAuth2 accounts table.

  • Default: {prefix}oauth2_accounts (e.g., o2p_oauth2_accounts)
DB_TABLE_OAUTH2_ACCOUNTS='o2p_oauth2_accounts'

Experimental Features

O2P_PASSKEY_PROMOTION

Prompt users to register a passkey after OAuth2 login. When a user logs in via OAuth2 without an existing passkey, a registration modal can be shown.

  • Default: unset (disabled)
ValueDescription
unsetDisabled, no promotion
askShow a confirmation modal asking the user to register a passkey
forceDirectly show the passkey registration dialog (skip confirmation)
O2P_PASSKEY_PROMOTION=ask

The promotion uses a UA + AAGUID heuristic to detect whether the user’s platform authenticator is likely available, avoiding prompts on unsupported devices.

Configuration Examples

Development (SQLite + Memory)

Minimal configuration for local development:

# Required
ORIGIN='http://localhost:3000'
OAUTH2_GOOGLE_CLIENT_ID='your-dev-client-id.apps.googleusercontent.com'
OAUTH2_GOOGLE_CLIENT_SECRET='your-dev-client-secret'
OAUTH2_ISSUER_URL='https://accounts.google.com'

# Storage - lightweight options for development
GENERIC_DATA_STORE_TYPE=sqlite
GENERIC_DATA_STORE_URL='sqlite:./dev.db'
GENERIC_CACHE_STORE_TYPE=memory

For testing with in-memory storage:

GENERIC_DATA_STORE_TYPE=sqlite
GENERIC_DATA_STORE_URL=':memory:'
GENERIC_CACHE_STORE_TYPE=memory

Production (PostgreSQL + Redis)

Recommended configuration for production deployments:

# Required
ORIGIN='https://your-domain.example.com'
OAUTH2_GOOGLE_CLIENT_ID='your-prod-client-id.apps.googleusercontent.com'
OAUTH2_GOOGLE_CLIENT_SECRET='your-prod-client-secret'
OAUTH2_ISSUER_URL='https://accounts.google.com'

# Production storage
GENERIC_DATA_STORE_TYPE=postgres
GENERIC_DATA_STORE_URL='postgresql://user:password@db-host:5432/production_db'
GENERIC_CACHE_STORE_TYPE=redis
GENERIC_CACHE_STORE_URL='redis://redis-host:6379'

# Security - CHANGE THIS!
AUTH_SERVER_SECRET='your-cryptographically-secure-random-string'

# Optional: Customize routes
O2P_ROUTE_PREFIX='/auth'

# Optional: Extend session duration (1 hour)
SESSION_COOKIE_MAX_AGE=3600

Multi-Domain Setup

For applications serving multiple domains:

ORIGIN='https://primary-domain.example.com'
WEBAUTHN_ADDITIONAL_ORIGINS='https://secondary-domain.example.com'

Custom Table Names

For integrating with existing database schemas:

DB_TABLE_PREFIX='myapp_auth_'
DB_TABLE_USERS='myapp_auth_users'
DB_TABLE_PASSKEY_CREDENTIALS='myapp_auth_passkeys'
DB_TABLE_OAUTH2_ACCOUNTS='myapp_auth_oauth2'