Use when an app uses Auth0 and needs tests for its tenant config, login flows or Action scripts: per-PR or namespaced tenants, Universal Login, PKCE, client credentials, Rules and Hooks, and config drift with a0deploy. Generic OAuth flows are oauth-flow-test-author.
The canonical home for this skill is testland/auth0-tests
Tests against an Auth0 tenant fall into three layers:
a0deploy and commit the YAML as
fixtures for the config-drift check (Step 2).onExecutePostLogin
with a stub api and asserting on api.access.deny (Step 4);
apply the legacy callback signature for surviving Rules / Hooks
(Step 5).a0deploy config-drift diff into CI
(Step 8).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.
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.
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.
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.
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.
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.
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.
- 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 checkA 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-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) |
keycloak-tests,
okta-tests - sister IdP toolsoauth-flow-test-author,
session-management-test-author - build-an-X authorstestland/qa
aa16752
Canonical home
since Jul 23, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.