auth0-tests
Authors tests against Auth0 - uses tenant isolation strategy (per-PR tenant or shared dev tenant with namespaced data); exercises Universal Login + auth-code-with-PKCE + client-credentials + RO-password (legacy) flows; tests Action scripts (Auth0's serverless extension hooks); tests Rules / Hooks (deprecated but still common); integrates with Auth0 Deploy CLI (`a0deploy`) for environment parity. Use when the user works with Auth0 SaaS and needs unit / integration tests for tenant config, auth flows, or Action scripts. Does not cover session lifecycle (refresh-token rotation, silent re-auth): use session-management-test-author for that. Differentiates from oauth-flow-test-author by Auth0-tenant specifics: Action scripts, Rules / Hooks, a0deploy config-drift, and Universal Login.
Install with skills.sh (any agent)
npx skills add testland/qa --skill auth0-testsauth0-tests
Overview
Tests against an Auth0 tenant fall into three layers:
When to use
How to use
Step 1 - Tenant strategy
Three patterns, per team scale:
| Pattern | Pros | Cons |
|---|---|---|
| Per-PR tenant (Auth0 sandbox plan) | Full isolation; safe destructive tests | Requires Auth0 plan supporting many tenants |
| Shared dev tenant + namespaced fixtures | Cheap | Test interference risk; cleanup discipline |
| Mocked OIDC server (e.g., mock-oauth2-server) | No Auth0 dep; fast | Doesn't catch Auth0-side behavior |
For tenant-level tests pick per-PR; for app-side flow tests, mocked OIDC is sufficient + faster.
Step 2 - Auth0 Deploy CLI for config parity
The a0deploy CLI exports tenant config to YAML/JSON, supports diff + apply across tenants. Pattern:
# Export dev tenant
a0deploy export -c config.json --output_folder tenant-fixtures/
# Diff against staging
a0deploy export -c config-staging.json --output_folder tenant-staging/
diff -r tenant-fixtures/ tenant-staging/
# Apply to staging from dev as source of truth
a0deploy import -c config-staging.json --input_file tenant-fixtures/tenant.yamlTests verify the export hasn't drifted unexpectedly:
a0deploy export -c config.json --output_folder tmp-current/
diff -r tenant-fixtures/ tmp-current/ # expect empty if no driftSource: auth0.com/docs/deploy-monitor/deploy-cli-tool.
Step 3 - Test the OIDC token endpoint
Auth0's token endpoint:
https://{your-domain}.auth0.com/oauth/tokenFor client-credentials (M2M) flow:
import requests
def test_m2m_token(auth0_domain, client_id, client_secret, audience):
response = requests.post(
f"https://{auth0_domain}/oauth/token",
json={
"grant_type": "client_credentials",
"client_id": client_id,
"client_secret": client_secret,
"audience": audience,
},
)
assert response.status_code == 200
body = response.json()
assert "access_token" in body
assert body["token_type"] == "Bearer"For interactive flows (authz code), use Playwright to drive the Universal Login UI (Auth0-hosted login page) and capture the redirect.
Source: auth0.com/docs/api/authentication.
Step 4 - Test Auth0 Actions (current generation)
Actions are the current Auth0 serverless extension model (post-Hooks). Each Action exports a handler:
// post-login.js
exports.onExecutePostLogin = async (event, api) => {
if (event.user.email_verified === false) {
api.access.deny('Email not verified');
}
};Unit-test pattern with Auth0's testing library:
const { onExecutePostLogin } = require('./post-login');
describe('post-login Action', () => {
it('denies access for unverified email', async () => {
const api = {
access: { deny: jest.fn() },
};
const event = {
user: { email_verified: false },
};
await onExecutePostLogin(event, api);
expect(api.access.deny).toHaveBeenCalledWith('Email not verified');
});
});Source: auth0.com/docs/customize/actions.
Step 5 - Test Rules + Hooks (legacy)
Rules + Hooks are deprecated as of 2024 (per Auth0 deprecation notices) but many production tenants still use them. Unit-test pattern is similar to Actions but with the legacy callback signature:
function emailVerifiedRule(user, context, callback) {
if (!user.email_verified) {
return callback(new UnauthorizedError('Email not verified'));
}
callback(null, user, context);
}
// Test
emailVerifiedRule(
{ email_verified: false },
{},
(err, user, ctx) => {
expect(err.message).toBe('Email not verified');
}
);For Auth0 Hooks, similar pattern with the hook-specific event shape.
Step 6 - Test session management
Auth0-managed sessions (refresh tokens, silent auth): refresh-token rotation is configurable per-application; tests should verify the rotation behaves as configured. For the full nine-point session checklist (cookie attributes, fixation, idle / absolute timeout, concurrent-session policy, server-side logout, CSRF, session binding) against the app's own session cookie, see references/session-checklist.md. Cross-tool session patterns live in session-management-test-author.
Step 7 - Mock OIDC server alternative
For fast unit tests of the application's OIDC integration without Auth0 calls:
docker run -p 8080:8080 ghcr.io/navikt/mock-oauth2-server:0.5.10Then point the application at http://localhost:8080/default/.well-known/openid-configuration. Tests run against the mock; per-PR Auth0 tenant unnecessary.
Step 8 - CI integration
- run: npm install
- run: npm test # unit tests including Actions
- run: a0deploy export -c .auth0/config.json --output_folder /tmp/auth0-current
- run: diff -r .auth0/tenant-fixtures /tmp/auth0-current # config-drift checkWorked example
A team ships a post-login Action that blocks sign-in for unverified emails. On a shared dev tenant with namespaced fixtures (Step 1), they export config with a0deploy export -c config.json --output_folder tenant-fixtures/ and commit it (Step 2). They unit-test the handler by passing event.user.email_verified = false and a stub api, then assert api.access.deny was called with 'Email not verified' (Step 4). CI runs npm test, then re-exports and diff -rs against tenant-fixtures/; a stray dashboard change to the Action fails the drift diff before it reaches staging (Step 8).
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Share a single Auth0 tenant for all envs | Config changes intermingle; staging breaks prod | Per-env tenants + a0deploy parity (Step 2) |
| Test Actions only via end-to-end | Slow; tests pass for wrong reasons | Unit-test Actions directly (Step 4) |
| Use password grant for new flows | Deprecated per RFC 9700 | Auth Code + PKCE (Step 3) |
| Skip config-drift CI check | Manual changes in dashboards never reach prod | Always diff exports (Step 8) |
Limitations
References
Auth0 session-management checklist
View source (opens in new window)Auth0 session-management checklist
Auth0-managed sessions (refresh tokens, silent auth): see session-management-test-author for the cross-tool pattern. Auth0-specific: refresh-token rotation is configurable per-application; tests should verify the rotation behaves as configured.
The base pattern, per OWASP ASVS (opens in new window) V3 (Session Management): cover all nine points against the application's own session cookie, then add the Auth0-specific rotation assertion.
Use a time-freezing fixture (e.g. freezegun) for steps 3 and 4 so timeout tests don't sleep.
Related skills
keycloak-tests
Authors and runs integration tests against Keycloak - uses Testcontainers Keycloak module to spin up an isolated server per test class, imports realm JSON for fixtures, exercises OIDC discovery / token endpoint / token introspection / admin REST API; tests password / authorization-code / client-credentials / token-exchange flows; covers UMA (User-Managed Access) permission tickets. Use when the user works with self-hosted Keycloak and needs unit / integration tests for realms, clients, users, or auth flows.
mfa-flow-test-author
Build-an-X workflow for authoring automated tests covering multi-factor authentication flows: TOTP (RFC 6238, deterministic codes from a known secret + fixed time), HOTP (RFC 4226, counter-based), SMS/email OTP, WebAuthn/passkey registration and authentication via Chrome DevTools Protocol virtual authenticator (WebAuthn L2 §11), recovery codes, MFA enrollment, and step-up authentication challenges. Use when the team needs end-to-end MFA test coverage beyond what oauth-flow-test-author covers, or when introducing a new second factor to an existing auth surface.
oauth-flow-test-author
Build-an-X for OAuth 2.0 / OIDC flow tests - authorization-code with PKCE per RFC 7636 (canonical for browser/native/mobile clients), client-credentials per RFC 6749 §1.3.4 (M2M), refresh-token rotation per RFC 9700 (token-binding + reuse-detection), state parameter for CSRF defense per RFC 6749 §10.12, nonce parameter for OIDC ID-token replay defense, scope-grant verification, redirect-URI strict matching. Use when authoring tests for any OAuth/OIDC client or resource server, regardless of the underlying IdP (Keycloak / Auth0 / Okta / mock).
okta-tests
Authors tests against Okta - uses org-isolation strategy (per-PR org via Okta Developer Edition vs shared org with namespaced data); tests sign-in policy + MFA enforcement; exercises Okta Identity Engine (OIE) workflows including factor enrollment, recovery flows, and SCIM provisioning; tests scoped API tokens for least-privilege automation. Use when the user works with Okta as IdP and needs unit / integration tests for org config, sign-in policies, or OIE workflows.
session-management-test-author
Build-an-X for session management tests per OWASP ASVS V3 - cookie attribute coverage (Secure / HttpOnly / SameSite=Strict|Lax), session-fixation defense (regenerate session ID on login), absolute + idle timeout, concurrent-session limits, logout invalidation across devices, CSRF token handling, session-binding to TLS / IP / device fingerprint. Use when authoring tests for any web app's session layer, regardless of framework (Express session, Django sessions, Spring Security, ASP.NET, Rails, etc.).