Skip to content

Auth strategies

An actor’s auth: block says how to obtain credentials; inject: says how to attach them to every request that actor makes. Pick a strategy by how your API issues credentials.

StrategyUse whenNetwork call
simpleOne login request returns a tokenyes
chainLogin takes several steps — OTP, MFA, tenant selectyes
basicHTTP Basicno
api_keyA static key in a header, query param, or cookieno
bearerYou already have a tokenno
oauth2_client_credentialsMachine-to-machine OAuth 2yes
oauth2_passwordOAuth 2 resource-owner password grantyes
oauth1OAuth 1.0a, HMAC-SHA1 signedno
aws_sigv4AWS Signature v4no
jwtYou sign your own JWTno
mtlsClient-certificate TLSno

strategy: defaults to simple. An unrecognised value silently falls back to simple — note oauth2 alone is not valid, it’s oauth2_client_credentials.

One request, extract a token. The most common shape.

actors/vendor.yaml
name: vendor
description: Marketplace vendor with email/password auth
auth:
strategy: simple
method: POST # default POST
path: /api/v1/auth/vendor/login
body:
email: "{{env.vendor_email}}"
password: "{{env.vendor_password}}"
expect_status: 200
extract:
token: $.data.accessToken
refresh_token: $.data.refreshToken
vendor_id: $.data.user.id
session:
ttl: 15m
inject:
headers:
Authorization: "Bearer {{vendor.token}}"

Everything extract produces becomes an actor-scoped variable — {{vendor.token}}, {{vendor.vendor_id}} — usable anywhere, not just in inject.

Keys: method, path, headers, body, expect_status (scalar only here), extract.

Several requests in order. Each step can use values the previous one extracted.

actors/customer.yaml
name: customer
auth:
strategy: chain
steps:
- id: request_otp
method: POST
path: /api/v1/auth/otp/request
body:
phone: "{{env.test_phone}}"
expect_status: 200
- id: verify_otp
method: POST
path: /api/v1/auth/otp/verify
body:
phone: "{{env.test_phone}}"
code: "000000"
expect_status: 200
extract:
token: $.data.accessToken
customer_id: $.data.user.id
inject:
headers:
Authorization: "Bearer {{customer.token}}"

Per-step keys: id, method, path, headers, body, expect_status, extract. steps must be a sequence.

No network call — the header is computed.

auth:
strategy: basic
username: "{{env.api_user}}"
password: "{{secret.API_PASSWORD}}"

No inject: needed; the Authorization: Basic … header is added for you.

auth:
strategy: api_key
key: "{{secret.API_KEY}}"
location: header # header | query | cookie
name: X-API-Key

key is the value. location and name are optional.

A token you already hold — from CI, or another actor.

auth:
strategy: bearer
token: "{{secret.SERVICE_TOKEN}}"

RFC 6749 §4.4. Reqloom fetches the token and injects it.

auth:
strategy: oauth2_client_credentials
token_url: https://auth.example.com/oauth/token
client_id: "{{env.client_id}}"
client_secret: "{{secret.CLIENT_SECRET}}"
scope: "orders:read orders:write" # optional

RFC 6749 §4.3 — the above plus user credentials.

auth:
strategy: oauth2_password
token_url: https://auth.example.com/oauth/token
client_id: "{{env.client_id}}"
client_secret: "{{secret.CLIENT_SECRET}}"
username: "{{env.user_email}}"
password: "{{secret.USER_PASSWORD}}"
scope: "profile" # optional

RFC 5849, HMAC-SHA1, signed per request.

auth:
strategy: oauth1
consumer_key: "{{env.consumer_key}}"
consumer_secret: "{{secret.CONSUMER_SECRET}}"
token: "{{env.oauth_token}}" # optional
token_secret: "{{secret.TOKEN_SECRET}}" # optional
realm: "Example" # optional

Signed per request with AWS Signature v4.

auth:
strategy: aws_sigv4
access_key: "{{env.AWS_ACCESS_KEY_ID}}"
secret_key: "{{secret.AWS_SECRET_ACCESS_KEY}}"
region: us-east-1
service: execute-api
session_token: "{{secret.AWS_SESSION_TOKEN}}" # optional, for STS

Sign your own JWT and send it as a bearer token.

auth:
strategy: jwt
secret: "{{secret.JWT_SIGNING_KEY}}"
algorithm: HS256 # HS256 (default) or HS512
payload: '{"sub":"user-123","role":"admin"}'

payload is a JSON object as a string.

Client-certificate TLS. Applies at the transport layer.

auth:
strategy: mtls
format: pem # pem (default) or p12
cert_path: /etc/certs/client.pem
key_path: /etc/certs/client-key.pem
key_password: "{{secret.KEY_PASSPHRASE}}" # optional
ca_cert_path: /etc/certs/ca.pem # optional

Certificate paths are not sandboxed to the project root — client certs usually live outside the repo. Prefer absolute paths.

A session is cached for ttl (default 15m) so you don’t re-authenticate on every run. When it expires, a refresh block avoids a full re-login:

session:
ttl: 15m
refresh:
method: POST
path: /api/v1/auth/refresh
body:
refresh_token: "{{vendor.refresh_token}}"
extract:
token: $.data.accessToken

Refresh extractions are merged into the existing session, so variables the login produced and refresh doesn’t (like vendor_id) survive. With no expect_status, any 2xx counts as success.

Malformed ttl values fall back to 15m silently — ttl: 15 minutes is not valid. See sessions & caching.

For a single endpoint that doesn’t justify an actor — a third-party callback, a health check on another host — put the credential on the operation:

check_partner:
method: GET
path: /partner/status
auth:
type: bearer
token: "{{secret.PARTNER_TOKEN}}"

type: accepts bearer, basic, apikey (or api_key), aws_sigv4, oauth1, oauth2, jwt, mtls, and inherit. Anything unrecognised means no auth is applied — silently.

Common shapes:

auth:
type: basic
username: admin
password: "{{secret.ADMIN_PW}}"
auth:
type: apikey
key: X-API-Key
value: "{{secret.API_KEY}}"
in: header # `query` puts it in the query string instead

type: inherit uses the project-wide default declared at the root:

reqloom.yaml
auth:
type: bearer
token: "{{secret.DEFAULT_TOKEN}}"

If an operation sets both actor: and auth:, inline auth is applied last and wins on the Authorization header.

Use an actor when the credential is an identity you’ll reuse — it gets session caching, refresh, and one place to change the password. Use inline auth for a one-off endpoint where standing up a login chain is more work than the test is worth.