Skip to content

System Config Reference

System config is the runtime configuration stored by seamless-auth-api in the system_config table.

Use it for auth behavior that operators may need to inspect or change, such as login methods, roles, token TTLs, WebAuthn relying-party settings, OAuth provider metadata, and lockout policy.

Do not store raw secrets in system config. Secrets belong in environment variables or a secret manager.


At startup, seamless-auth-api bootstraps each known config key.

For each key:

  1. if a system_config row already exists, the API uses that row
  2. if no row exists and a mapped env var exists, the API parses the env var and creates the row
  3. if no row exists and the key has a built-in default, the API creates the row with that default
  4. if no row exists, no env var exists, and no default exists, startup fails

That means env vars seed missing config rows. They do not overwrite rows that already exist.


Raw auth API routes:

MethodRouteRequired access
GET/system-config/rolesadmin:read
GET/system-config/adminadmin:read
PATCH/system-config/adminadmin:write

Through the Express adapter, use:

/auth/system-config/roles
/auth/system-config/admin

Successful updates return:

{
"success": true,
"updatedKeys": ["login_methods"]
}

The auth API logs system config reads, updates, and validation errors as auth events.


KeyEnv seedTypePurpose
app_nameAPP_NAMEstringDisplay name used in auth flows and TOTP issuer
default_rolesDEFAULT_ROLESstring arrayRoles assigned to new users
available_rolesAVAILABLE_ROLESstring arrayRoles allowed in the system
login_methodsLOGIN_METHODSlogin method arrayMethods offered after login starts
passkey_login_fallback_enabledPASSKEY_LOGIN_FALLBACK_ENABLEDbooleanWhether fallback methods can appear with passkey login
oauth_providersOAUTH_PROVIDERSJSON arrayOAuth provider metadata
lockout_policyLOCKOUT_POLICYJSON objectFailed-login lockout policy
access_token_ttlACCESS_TOKEN_TTLdurationAccess token and access cookie TTL
refresh_token_ttlREFRESH_TOKEN_TTLdurationRefresh cookie TTL
rate_limitRATE_LIMITnumberRequest rate limit value
delay_afterDELAY_AFTERnumberSlowdown threshold
rpidRPIDstringWebAuthn relying party ID
originsORIGINSURL arrayWebAuthn allowed browser origins

Built-in defaults exist for:

KeyDefault
login_methods["passkey", "magic_link"]
oauth_providers[]
passkey_login_fallback_enabledtrue
lockout_policyenabled, 10 failures, 15-minute window, 15-minute lockout

Other keys must come from env or an existing database row.


Env valueParsing rule
DEFAULT_ROLESComma-separated list
AVAILABLE_ROLESComma-separated list
LOGIN_METHODSComma-separated list
ORIGINSComma-separated URL list
OAUTH_PROVIDERSJSON array
LOCKOUT_POLICYJSON object
RATE_LIMITNumber
DELAY_AFTERNumber
PASSKEY_LOGIN_FALLBACK_ENABLEDtrue means true; anything else is false
ACCESS_TOKEN_TTLDuration string
REFRESH_TOKEN_TTLDuration string
RPIDString
APP_NAMEString

Duration strings in system config use:

30s
15m
1h
7d

The current schema accepts s, m, h, and d for system config TTLs.


Allowed values:

MethodMeaning
passkeyWebAuthn/passkey login
magic_linkEmail magic-link login
email_otpEmail one-time code
phone_otpPhone/SMS one-time code
oauthExternal OAuth provider login

Example:

{
"login_methods": ["passkey", "magic_link", "email_otp", "phone_otp", "oauth"],
"passkey_login_fallback_enabled": true
}

When passkey login is usable and passkey_login_fallback_enabled is false, the auth API returns only passkey as the continuation method.

OAuth is configured as a login method, but it does not appear as a fallback from identifier-based /login. Use /oauth/providers or listOAuthProviders() to render OAuth buttons.


default_roles are assigned to new users.

available_roles is the list operators can assign through admin flows.

Rules enforced on update:

  • every default_roles value must exist in available_roles
  • roles currently assigned to users cannot be removed from available_roles
  • available_roles cannot remove a role that is still part of the existing default roles

Scoped admin roles are supported by auth route guards:

RoleGrants
adminbroad admin access
admin:readread access
admin:writewrite access and read access

Use the narrowest role that matches the route you are protecting.


oauth_providers is an array of provider configs.

{
"oauth_providers": [
{
"id": "google",
"name": "Google",
"enabled": true,
"clientId": "google-client-id.apps.googleusercontent.com",
"clientSecretEnv": "GOOGLE_CLIENT_SECRET",
"authorizationUrl": "https://accounts.google.com/o/oauth2/v2/auth",
"tokenUrl": "https://oauth2.googleapis.com/token",
"userInfoUrl": "https://openidconnect.googleapis.com/v1/userinfo",
"scopes": ["openid", "email", "profile"],
"redirectUris": ["https://app.example.com/oauth/callback"],
"subjectJsonPath": "sub",
"emailJsonPath": "email",
"emailVerifiedJsonPath": "email_verified",
"nameJsonPath": "name",
"allowSignup": true,
"accountLinking": "email",
"requireEmailVerified": true
}
]
}

clientSecretEnv is an env var name. The actual provider secret must live in that env var, not in system config.

redirectUri and redirectUris are allowlists. If present, requested OAuth callback URLs must match exactly.


Default policy:

{
"enabled": true,
"maxFailures": 10,
"windowSeconds": 900,
"lockoutSeconds": 900
}

The current lockout policy counts recent failures for:

  • login_failed
  • webauthn_login_failed
  • verify_otp_failed
  • totp_failed
  • magic_link_failed

When a user is locked, the auth API returns 423 with error: "account_locked" and retryAfterSeconds.


KeyUse
rpidExpected WebAuthn relying party ID
originsBrowser origins accepted for WebAuthn verification
app_nameRelying party display name during registration

Local example:

{
"rpid": "localhost",
"origins": ["http://localhost:5173", "http://localhost:5174"],
"app_name": "Seamless Auth Example"
}

Production example:

{
"rpid": "example.com",
"origins": ["https://app.example.com", "https://admin.example.com"],
"app_name": "Example"
}

APP_ORIGINS is separate. It controls CORS for who may call the auth API. origins controls WebAuthn verification.


seamless-auth-api caches system config in process and invalidates the cache after a successful PATCH /system-config/admin.

If you edit the system_config table outside the API, expect existing processes to keep cached values until they reload or the cache expires.


Keep these in env vars or a secret manager:

  • API_SERVICE_TOKEN
  • COOKIE_SIGNING_KEY
  • REFRESH_TOKEN_LOOKUP_SECRET
  • TOTP_SECRET_ENCRYPTION_KEY
  • OAUTH_STATE_SECRET
  • OAuth provider client secrets such as GOOGLE_CLIENT_SECRET
  • SEAMLESS_JWKS_ACTIVE_KID
  • SEAMLESS_JWKS_KEY_<kid>_PRIVATE
  • JWKS_PUBLIC_KEYS

System config may reference secret env var names, such as clientSecretEnv, but should not contain raw secret values.


  1. Read current config from /auth/system-config/admin.
  2. Patch only the keys you intend to change.
  3. Confirm the response includes the expected updatedKeys.
  4. Test login, WebAuthn, OAuth, and admin flows affected by the change.
  5. Keep env vars aligned for any secrets referenced by system config.

Example patch:

{
"login_methods": ["passkey", "magic_link", "email_otp"],
"passkey_login_fallback_enabled": true
}