Auth profiles
Auth profiles let the same API scenario run as different identities. Use them to test whether admins, regular users, viewers, unauthenticated clients, and invalid tokens get the right access.How they work
An environment can carry many named auth profiles. Each profile has its own credentials and login config. At run time, a scenario picks one profile and inherits that profile’s token for every step. A profile has two flavors:- API: posts credentials to a login endpoint and extracts a token from the response.
- UI: drives Playwright through the login form and captures storage state (plus sniffs a bearer token from network traffic for the API fallback).
staging environment:
| Profile name | type | What it logs in as |
|---|---|---|
admin | api | A privileged account that can read and write everything |
user | api | A regular account scoped to its own resources |
viewer | api | A read-only account |
user, capture that user’s userId, then run as a different user profile and try to read the first user’s resource. The expected result is 403. If the API returns 200, the assertion fails and Qodex opens a critical finding.
Precedence
For API steps, the runner picks an auth source in this exact order:- Static
authTokenon the environment, if set directly. Overrides everything. - Cached bearer token if the cache is still fresh (TTL 30 minutes).
api_login_configon the environment (or the chosenauth_profile.login_config). Run the login, extract the token.- Browser fallback via
ui_login_steps. Drive Playwright through the login form, sniff the bearer token off the network.
ui_login_steps.
The api_login_config shape
The HTTP login configuration tells Qodex how to exchange credentials for a token.url: where to POST. Must resolve to an absolute URL after${var}substitution. Bare paths are rejected.method: usuallyPOST. The runner accepts any HTTP verb.headers: any headers the login endpoint needs. DefaultContent-Type: application/json.body: the request body. Plain JSON for most APIs, form-encoded for legacy.tokenPath: dot-notation JSONPath into the response body.data.access_tokenreadsresponse.data.access_token. The runner uses a small JSONPath subset, dots only. For exotic paths, write a postscript instead.
When this matters
The whole point of running tests as multiple identities is authorization correctness:- IDOR (insecure direct object reference): a
userprofile should not be able to read another user’s resources. Run the same scenario as two differentuserprofiles, capture an ID from one, request it as the other, assert 403. - BOLA (broken object-level authorization): same idea at the object level. List your orders as one user, then try to load one of those order IDs as another user.
- Role escalation: a
viewershould not be able to write. Run the write scenarios asviewerand assert 403 across the board. - Endpoint-level auth gating: an unauthenticated client should get 401 on protected routes. Use a profile with no token (or a deliberately invalid one) to assert that.
Sample environment with two profiles
On the roadmap
Related
Scenarios
See where step.auth attaches.
Chaining and postscripts
Capture tokens from a login response.
API Playground
Run requests with any auth profile.
Auto-verification on save
What gets checked the moment you save.