You have now seen all four auth types. Use this table on every new partner.
Auth decision table
| The partner guide says… | Auth type | HTTP call to get a token? | Cached? | Key fields |
|---|---|---|---|---|
| “Send this key in header X” | TOKEN | No | No | parameters.token, headerName, tokenPrefix |
| “Use HTTP Basic” | BASIC | No | No | parameters.username/password, tokenPrefix "Basic" |
| “Log in with username/password, then use the token” | USER_CREDENTIALS | Yes | Yes | baseUrl, authPath, bodyTemplate, tokenConfig |
| “OAuth2 client_credentials grant” | CLIENT_CREDENTIALS | Yes | Yes | baseUrl, authPath, query/body, tokenConfig |
| “No authentication” (public API, IP allow-list) | no auth block | No | — | — |
tokenConfig reference
| Field | Used by | What it does | If wrong |
|---|---|---|---|
| storageKey | credentials flows | Global cache key for the token | Two partners sharing a key overwrite each other’s token |
| headerName | all | Header that carries the token | Missing tokenConfig → 500 at runtime (it saves fine) |
| tokenPrefix | all | Text + space before the token | Partner answers 401 |
| extractPath | credentials flows | JSONata path to the token in the auth response | 500 TOKEN_EXTRACTION_ERROR |
| expiryBuffer | credentials flows | Seconds to keep the token (literal or path) | 500 TOKEN_EXPIRY_EXTRACTION_ERROR |
When a partner says 401 or 403:
Is it the partner’s 401 body (credentials or header wrong) or an engine code like TOKEN_EXTRACTION_ERROR (login worked, path wrong)?
Check type, baseUrl + authPath, bodyTemplate and tokenConfig. Remember the output shows secrets in clear text.
Check that the header name is right and that it was sent; the value is redacted. To see prefix and spacing, run the mapping test, or point the endpoint at a mock rule that matches the exact header value.
If the partner rotated credentials, a cached token can live until expiryBuffer runs out. Use a short buffer while testing; changing the storage key forces a fresh login.
Secrets as environment variables: the exact format
| Value in the mapping | What the engine does | Verdict |
|---|---|---|
"password": "${KEZA_PASSWORD}" |
Replaces the whole value with the environment variable KEZA_PASSWORD | Correct |
"password": "${keza.password}" |
Dotted names work the same way | Correct |
"Authorization": "${KEZA_BASIC_HEADER}" |
Whole header value in one variable (e.g. Basic dmlj…) |
Correct |
"token": "Bearer ${KEZA_API_KEY}" |
Partial string: sent literally as Bearer ${KEZA_API_KEY} |
Wrong: put the prefix in tokenPrefix |
"password": "$KEZA_PASSWORD", "{{KEZA_PASSWORD}}" |
Plain text, sent as written | Wrong |
"password": $env.KEZA_PASSWORD |
An undefined JSONata variable: the key is dropped | Wrong |
"${KEZA_PASSWORD}" not defined on the environment |
500 MISSING_ENVIRONMENT_VARIABLE before any partner call, even with a cached token |
Ask the platform team to define it |
${…} in the Endpoint url |
Rejected at save (400): the URL may not contain $ |
Wrong |
Secrets · who defines the variables
Only the platform team adds environment variables, once per environment (staging, production). Send them the variable name and the secret through a secure channel, never in a ticket. In this course the reference endpoints keep training literals so you can reproduce every call; the capstone go-live note must list the variables you would use.
Gotcha · Mock mode still logs in for real
When an endpoint is switched to its mock (Module 6), the engine replaces only the endpoint URL. The auth block still calls
auth.baseUrl. If that is the real partner, your “mock” test depends on the partner’s login. Give the mock its own login mock, or pointbaseUrlat the mock host while testing.
Your CLIENT_CREDENTIALS endpoint fails with 500, responseCode null, responseMessage TOKEN_EXTRACTION_ERROR. What is certain?
C. The engine got a token response and failed to extract from it. A wrong secret usually gives the token server’s own 401.
Two endpoints call the same partner with the same login but different scopes. They share storageKey KEZA_TOKEN. What will you see?
D. The key is global and a cached token is reused until expiryBuffer runs out; a later login does not replace a live token. Use one key per distinct credential or scope.
Your turn · audit your own auth blocks
For each endpoint you built in 3.1–3.3, write one line in your evidence pack: the auth type, the production environment variables and the exact JSON with placeholders (for example
"parameters": { "token": "${KEZA_API_KEY}" }). Check each line against the format table above.Then set
"expiryBuffer": 30on${YOUR_FIRST_NAME}_KEZA_SCHOLARSHIP_FETCHand call it twice, 40 seconds apart. Done when: Kibana shows a…/oauth/tokenrequest for both calls (the token expired in between). Set it back to 300.
← 3.3 OAuth2 client credentials: scholarships · 4.1 Transform the response: dropdown options →