Skip to main content

Security Best Practices

A short, actionable checklist for the two people who decide how secure a LumoAuth deployment is: the integrator wiring an application to it, and the organization admin configuring it. Every item reflects how the product behaves today; where a default already does the safe thing, the item says so. For the underlying rules see Credentials and access model.


For integrators​

Choose the narrowest credential​

Do thisWhy
Use an API key with only the scopes the job needs (admin:users:read, not admin). One key per job.A key with a single scope only reaches that resource, and a :read scope cannot mutate. A leaked narrow key is a small problem. See API keys.
For OAuth-based automation, request an admin scope on the token (admin or admin:<resource>:<read|write>).openid profile email tokens get 403 on the Admin API even for administrators. Only first-party clients can be granted admin scopes. See Admin API authentication.
Send the credential on every request. Never expect a cookie back.API keys and Bearer tokens are stateless: they never create a browser session and are refused on the portal and account pages.
Use the SCIM provisioning token (SCIM is the standard for automatic user provisioning) (or an access token with the scim scope) for SCIM, never HTTP Basic with an admin's password.Basic auth is a single factor; it is refused for users enrolled in MFA (multi-factor authentication), and ID, logout, JIT and agent tokens are refused on SCIM. See SCIM API.

Validate what comes back​

Do thisWhy
Validate iss on the authorization response and in every token against the issuer in the discovery document (byte-compare).Defends against mix-up attacks (the issuer identifier in the response). LumoAuth's iss is always identical to discovery: …/orgs/{slug}/api/v1 or your custom domain. See OAuth security.
Check aud, exp and the signature against jwks_uri; use introspection when you need instant revocation.A valid signature alone does not prove the token was meant for you.
Use PKCE (a one-time secret that protects the sign-in code) for every client and exact-match redirect URIs.Required for public clients; javascript: and data: redirect URIs are rejected at registration.
Turn on DPoP for tokens that leave a server, and keep the server-provided nonce off unless every client implements the use_dpop_nonce retry.DPoP (a sender-constrained token) binds a token to a key so theft is useless. The nonce is opt-in per organization via settings.security.dpop_require_nonce because enabling it breaks clients that do not retry. See Token management.
Send the CSRF token with POST /logout and with session-authenticated Admin API writes.All logout links are token-bearing forms; a bare POST /logout is refused.
Standard

Issuer identifier in the response. Solves mix-up attacks where a response is replayed from a different authorization server. The one thing to do: compare the iss parameter on the callback with the discovery issuer before exchanging the code. See the standards reference.

For organization admins​

Authentication​

Do thisWhy
Offer passkeys (sign-in with a device biometric or security key) and require MFA (multi-factor authentication) for admins.Passkeys are phishing-resistant and always require user verification (biometric or PIN); assertions without it are rejected. See Passkeys.
Turn on Adaptive MFA and breached-password checks.Step-up only on risky sign-ins; block reused breached passwords. See Adaptive MFA.
Keep the default lockout and rate limits.The hosted OAuth login page, the form login and the LDAP path share the same limiter and lockout accounting, keyed by IP and e-mail, and return one generic failure message.
Leave allow_root_admin_login off (the default).It lets LumoAuth operators sign in through your hosted login page. It is changed only by LumoAuth operators at your request; every such login is audited at critical severity. See Organization settings.

Provisioning and access control​

Do thisWhy
Review the SCIM policy toggles before connecting an IdP: user creation, updates, deletion, group operations, protected attributes and the deprovisioning action.These are enforced by the SCIM API, not just shown in the portal. A protected attribute is left untouched on update; a disallowed operation is refused. Set them at /orgs/{orgId}/portal/integrations/scim. See SCIM provisioning.
Give default roles for social login no admin-conferring permissions.Admin and system roles are rejected as social-login defaults, and a role can never confer more than the assigning actor holds.
Set an allowed reviewers list on ServiceNow and Jira approval channels.Those channels assert the reviewer's e-mail rather than proving it; the list caps what a leaked callback token can do. See Approval channels.
Least privilege everywhere: separate admin roles, review assignments quarterly, use groups.Fewer people with settings.manage means fewer people who can mint admin credentials.

Organization security​

Do thisWhy
Rotate signing keys and client secrets on a schedule.Limits the window of a compromise. Client secrets are hashed and never re-displayed. See Signing keys.
Enable audit logging, alert channels and a SIEM (security information and event management system) export.Failed logins, lockouts, root-admin fallback logins and scope-check failures are all audited. See Audit logs.
Use a custom domain and validate every outbound URL you configure (webhooks, LDAP, log sinks) points where you expect.Outbound calls are SSRF-guarded and DNS-pinned, but a typo still sends data to the wrong host.

Common mistakes​

  • 403 forbidden on the Admin API with an OAuth token. The token has no admin or admin:<resource>:<read|write> scope. Request one on a first-party client, or use an API key.
  • 403 insufficient scope with an API key. The key was created with a narrower scope than the endpoint needs (for example admin:users:read on a POST). Create a key with the :write scope for that resource.
  • No session after calling an API with a Bearer token. Expected. Present the credential on every request; log in through the browser for the portal.
  • SCIM returns 401 with an admin's username and password. The admin has MFA enrolled. Use the provisioning token.
  • Passkey sign-in fails on a security key without a PIN. User verification is required. Set a PIN on the key or use a platform authenticator.

Standards used on this page​

Plain nameStandard
Issuer identifier in the responseRFC 9207
Proof Key for Code Exchange (PKCE)RFC 7636
Sender-constrained tokens (DPoP)RFC 9449

See the standards reference for what each one covers and how LumoAuth uses it.