// docs / baas security / auth0 hardening
Auth0 security checklist: 22 items
Auth0 is an identity-as-a-service platform with an enormous surface β applications, APIs (resource servers), tenants, actions, rules (legacy), connections, and grants. Misconfiguration of any one of them is an auth bypass. This checklist is a 22-item audit across applications, callback / logout allowlists, tokens and refresh rotation, custom actions, RBAC, anomaly detection, and ongoing monitoring. Each item is verifiable in the Auth0 Dashboard in under 10 minutes.
For the equivalent checklist on Clerk, see <clerkArticle>Clerk security checklist</clerkArticle>. For background on why identity-layer misconfigurations are AI-tool blind spots, see <aiGaps>Why AI coding tools leave security gaps</aiGaps>.
Application type and grant types
The application type and the enabled grant types are the highest-impact settings in Auth0. Getting them wrong opens classes of attack that no amount of frontend code will close.
- <strong>Use Application Type = <em>Single Page Application</em> for browser-only apps and <em>Regular Web Application</em> for server-rendered apps.</strong> The wrong type allows the wrong grant types β e.g., a Regular Web App with the SPA grant enables PKCE-less Implicit flow, which leaks tokens via URL fragments.
- <strong>Disable the Implicit grant type on every application.</strong> Dashboard β Application β Advanced Settings β Grant Types β uncheck <em>Implicit</em>. Implicit flow returns tokens in URL fragments, where they are logged in browser history and analytics. Use Authorization Code with PKCE instead.
- <strong>Disable Password grant unless you have a documented need.</strong> Resource Owner Password Credentials (ROPC) grant requires you to handle user passwords yourself β defeating most of what you bought Auth0 for. Disable it unless integrating a legacy system.
- <strong>Enable Authorization Code with PKCE on every public client.</strong> Dashboard β Advanced Settings β OAuth β JsonWebToken Signature Algorithm = RS256, OIDC Conformant = enabled. PKCE is required for mobile apps and SPAs to prevent code interception.
Callback and logout URL allowlists
Open redirects on the OAuth callback path are a token-theft primitive. Auth0's allowlist is your only defense.
- <strong>Set Allowed Callback URLs to your exact production callback path β no wildcards.</strong> <code>https://yourapp.com/callback</code>, not <code>https://yourapp.com/*</code>. Wildcard callbacks let attackers redirect tokens to arbitrary subpaths on your domain.
- <strong>Set Allowed Logout URLs to a finite list.</strong> Same rule: explicit URLs only. An open logout redirect lets attackers craft phishing pages that look like your post-logout state.
- <strong>Set Allowed Web Origins to your production origin only.</strong> Used for silent authentication (token renewal via hidden iframe). A wildcard origin lets attacker pages perform silent auth against your tenant.
- <strong>Set Allowed CORS origins for the API endpoints, not the application.</strong> Tenant Settings β Advanced β Allowed CORS origins. Default is empty (restricted); only add explicit origins you control.
Tokens and refresh rotation
Token lifetime, refresh rotation, and signing algorithm decide the blast radius of any token leak.
- <strong>Enable Refresh Token Rotation.</strong> Application β Refresh Token Settings β Rotation. Each refresh issues a new refresh token and invalidates the old one. Combined with absolute expiry, this contains token theft.
- <strong>Set Refresh Token Reuse Interval to 0 (or as low as your replay tolerance allows).</strong> The reuse interval lets a token be used twice in the same window β turn it off unless you have a specific reason to keep it.
- <strong>Set Absolute Refresh Token Expiry to 14-30 days, not infinity.</strong> Application β Refresh Token Expiration β Absolute Expiration. Auth0 defaults to <em>Inactivity</em>-only, which means an idle session can persist for years.
- <strong>Set JWT Signature Algorithm to RS256.</strong> Application β Advanced β OAuth β JsonWebToken Signature Algorithm. RS256 uses asymmetric signing so the client cannot forge tokens. Never use HS256 for client-facing applications.
- <strong>Verify <code>aud</code> and <code>iss</code> claims on every JWT your API receives.</strong> Use the official Auth0 SDK on the server side β it verifies these automatically. Hand-rolled JWT parsing usually skips audience validation, which is an auth bypass.
Actions and custom code
Auth0 Actions (and legacy Rules) run server-side at login and other lifecycle events. They have access to the entire request context. Insecure code here is a tenant-wide vulnerability.
- <strong>Never log <code>event.user</code> or <code>event.transaction</code> as a whole object.</strong> These contain email addresses, IP addresses, and other PII. Use field-level logging only, and only log what you need.
- <strong>Use the secrets store for any API key or webhook URL.</strong> Actions β Edit β Secrets. Never inline an API key as a string literal in action code β the code is visible to anyone with Action editor access on the tenant.
- <strong>Validate inputs before persisting them as user_metadata or app_metadata.</strong> A self-service action that writes <code>event.body.name</code> to <code>user.user_metadata.display_name</code> is a stored-XSS vector if your frontend renders that field without escaping.
RBAC and resource servers
If you use Auth0 RBAC, the role-to-permission mapping is your authorization layer. Get it wrong and any authenticated user can hit admin endpoints.
- <strong>Define Resource Servers (APIs) explicitly in the Auth0 Dashboard, not on the fly.</strong> Each API has an identifier (the <code>audience</code>), scopes, and signing settings. Without a registered API, all tokens are issued for the implicit "Auth0 Management API" β wrong audience.
- <strong>Configure Permissions per API and require them in your code with the <code>scope</code> claim.</strong> Don't check role membership in your application logic; check scopes in the access token. Scopes are the OAuth-native authorization mechanism.
- <strong>Test that an authenticated user without the required role / scope cannot hit privileged endpoints.</strong> Sign in as a normal user, try to call <code>POST /api/admin/users/delete</code>. Response must be <code>403</code>.
Anomaly detection and tenant logs
Auth0 emits high-signal events. Set them up to alert your team, not just sit in a log buffer.
- <strong>Enable Attack Protection: Bot Detection, Brute Force, Suspicious IP Throttling.</strong> Dashboard β Security β Attack Protection. Each is off by default on free tiers; turn them all on for production.
- <strong>Stream tenant logs to a SIEM or your application logs.</strong> Dashboard β Monitoring β Streams. Auth0 retains logs for 30 days on most plans; long-term retention requires a stream into your own system.
- <strong>Alert on <code>fcoa</code> (failed cross-origin auth) and <code>fp</code> (failed login) spikes.</strong> A burst of these in a short window is credential stuffing. Route to your on-call channel.
Next steps
Run a FixVibe scan against your production URL β the <code>baas.clerk-auth0</code> check flags Auth0 client secrets bundled in JavaScript and other identity-provider exposure classes. For the equivalent on Clerk, see <clerkArticle>Clerk security checklist</clerkArticle>. For the umbrella view across BaaS providers, read <baasScannerArticle>BaaS misconfiguration scanner</baasScannerArticle>.
