basic-auth
Validates the Authorization: Basic ... header against a configured username/password map and/or the gateway's consumers: section. Place it early in the request pipeline; downstream nodes can read the authenticated username from context.message and, in consumer mode, the attached consumer identity.
Configuration
| Key | Type | Default | Description |
|---|---|---|---|
users | object or array | — | Username→password credentials. Accepts either a map ({alice: s3cret}) or an array of {username, password} objects — the shape the web UI's node editor emits. Optional when use_consumers is set. |
use_consumers | boolean | false | Also resolve credentials against the gateway's consumers: section (their basic-auth: {username, password} credentials) and attach the matched consumer. At least one of users / use_consumers must be provided, otherwise policy compilation fails. |
anonymous_consumer | string | unset | Consumer name attached when no credential matches, instead of rejecting. |
hide_credentials | boolean | false | Strip the Authorization header before proxying upstream. |
realm | string | gateway | Realm advertised in the WWW-Authenticate challenge on rejection. |
- id: auth
type: basic-auth
config:
use_consumers: true
realm: internal-api
hide_credentials: true
Inline users (no consumer store) still work exactly as before:
- id: auth
type: basic-auth
config:
users:
alice: s3cret
bob: hunter2
realm: internal-api
Note: the UI node editor pre-fills realm with restricted; the plugin's own default (when the key is omitted) is gateway.
Behavior
The plugin base64-decodes the Authorization: Basic header into a username:password pair and resolves it in order:
- Inline
users— a matching username/password lets the request continue. - Consumer store (when
use_consumers: true) — the username is looked up against thebasic-authconsumer credentials and the presented password is checked against the matched consumer's stored password. On success the consumer identity is attached (consumer.*keys incontext.messageplusX-Consumer-Username/X-Consumer-Custom-IDheaders). - Anonymous fallback (when
anonymous_consumeris set) — if nothing matched, the named consumer is attached instead of rejecting.
On success the context passes through the success port. For back-compat the authenticated username is always written to context.message["user"].
On a missing header, malformed credentials, unknown user, or wrong password (and no anonymous fallback), the plugin sets a rejection on the response and exits through the denied port:
context.response.status_code=401- Body:
{"error": "unauthorized", "message": "Invalid credentials"}withcontent-type: application/json WWW-Authenticate: Basic realm="<realm>"challenge header
Ports
basic-auth declares three output ports: success, denied (a rejection is prepared), and error (never actually used — the plugin never fails). Like success, denied is a mandatory port: the policy compiler rejects any policy that leaves it unwired. Wire basic-auth.denied straight to client so the prepared 401 (with its WWW-Authenticate challenge) reaches the caller instead of continuing into upstream:
edges:
- from: basic-auth.success
to: upstream.in
- from: basic-auth.denied
to: client.in
Errors
This node never fails at execution time: it always returns through success, so its error port is never taken.