Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions docs/guide/ai-gateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,13 @@ The dispatcher owns *provider routing* and *catalog policy*. Layer middlewares o
paths:
/v1/chat/completions:
post:
security:
- bearerAuth: []
x-barbacane-middlewares:
- name: jwt-auth
- name: oidc-auth
config:
issuer: "https://auth.example.com"
issuer_url: "https://auth.example.com"
audience: "my-api"

# Per-tier model gating using request body + claims (cel body_json)
- name: cel
Expand Down
13 changes: 9 additions & 4 deletions docs/guide/dispatchers.md
Original file line number Diff line number Diff line change
Expand Up @@ -632,12 +632,13 @@ paths:
parameters:
- { name: bucket, in: path, required: true, schema: { type: string } }
- { name: key, in: path, required: true, allowReserved: true, schema: { type: string } }
security:
- bearerAuth: []
x-barbacane-middlewares:
- name: oidc-auth
config:
issuer: https://auth.example.com
issuer_url: https://auth.example.com
audience: my-api
required: true
x-barbacane-dispatch:
name: s3
config:
Expand Down Expand Up @@ -1197,10 +1198,14 @@ Client: GET /ws/echo?token=abc → Upstream: ws://echo.internal:8080/?token=abc
required: true
schema:
type: string
security:
- bearerAuth: []
x-barbacane-middlewares:
- name: jwt-auth
- name: oidc-auth
config:
required: true
issuer_url: "https://auth.example.com"
audience: "chat"
allow_query_token: true # browsers cannot set headers on a WebSocket
x-barbacane-dispatch:
name: ws-upstream
config:
Expand Down
26 changes: 16 additions & 10 deletions docs/guide/middlewares/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

All authentication middlewares set the standard [consumer identity headers](index.md#consumer-identity-headers) — `x-auth-consumer` and `x-auth-consumer-groups` — so downstream authorization plugins (notably [`acl`](authorization.md#acl)) don't need to know which auth plugin produced them.

- [`jwt-auth`](#jwt-auth) — JWT Bearer tokens with RS256/HS256 signatures
- [`apikey-auth`](#apikey-auth) — API keys from header or query parameter
- [`oauth2-auth`](#oauth2-auth) — Bearer tokens via RFC 7662 token introspection
- [`oidc-auth`](#oidc-auth) — OpenID Connect discovery + JWKS
- [`jwt-auth`](#jwt-auth): JWT bearer tokens verified against an inline public key (RSA or EC)
- [`apikey-auth`](#apikey-auth): API keys from header or query parameter
- [`oauth2-auth`](#oauth2-auth): Bearer tokens via RFC 7662 token introspection
- [`oidc-auth`](#oidc-auth): OpenID Connect discovery + JWKS
- [`basic-auth`](#basic-auth) — HTTP Basic per RFC 7617

---

## jwt-auth

Validates JWT tokens with RS256/HS256 signatures.
Validates JWT bearer tokens against a public key given inline as a JWK.

```yaml
x-barbacane-middlewares:
Expand All @@ -21,22 +21,28 @@ x-barbacane-middlewares:
issuer: "https://auth.example.com" # Optional: validate iss claim
audience: "my-api" # Optional: validate aud claim
groups_claim: "roles" # Optional: claim name for consumer groups
skip_signature_validation: true # Required until JWKS support is implemented
public_key_jwk: # Key that verifies the signature
kty: RSA
alg: RS256
n: "0vx7agoebGcQSuu..." # base64url modulus
e: AQAB
```

Accepted algorithms: RS256, RS384, RS512, ES256, ES384, ES512. HS256/HS512 and `none` are rejected.
Every token must carry a valid signature under `public_key_jwk`: without the key, tokens are rejected with `401` at the signature step. RSA keys verify `RS256`, `RS384` and `RS512`; EC keys (`crv`, `x`, `y`) verify `ES256` and `ES384`. `HS256`/`HS384`/`HS512` and `none` are rejected. When the key sets `alg` or `use`, the token must match them.

**Note:** Cryptographic signature validation is not yet implemented. Set `skip_signature_validation: true` in production until JWKS support lands. Without it, all tokens are rejected with 401 at the signature step.
To verify against keys an identity provider publishes at a JWKS URL, with rotation, use [`oidc-auth`](#oidc-auth).

### Configuration

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `public_key_jwk` | object | - | Public key as a JWK (RFC 7517) that verifies the token signature. Required for any token to be accepted |
| `issuer` | string | - | Expected `iss` claim. Tokens not matching are rejected |
| `audience` | string | - | Expected `aud` claim. Tokens not matching are rejected |
| `audience` | string | - | Expected `aud` claim. Tokens not matching are rejected. Strongly recommended |
| `clock_skew_seconds` | integer | `60` | Tolerance in seconds for `exp`/`nbf` validation |
| `groups_claim` | string | - | Claim name to extract consumer groups from (e.g., `"roles"`, `"groups"`). Value is set as `x-auth-consumer-groups` |
| `skip_signature_validation` | boolean | `false` | Skip cryptographic signature check. Required until JWKS support is implemented |
| `skip_signature_validation` | boolean | `false` | Test only: ignored by the compiled plugin, so it cannot disable verification |
| `jwks_url`, `public_key_pem` | string | - | Accepted but not used by `jwt-auth`; use `oidc-auth` for JWKS, or supply `public_key_jwk` |

### Context headers

Expand Down
16 changes: 9 additions & 7 deletions docs/guide/middlewares/authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ Policy-based access control via [Open Policy Agent](https://www.openpolicyagent.

```yaml
x-barbacane-middlewares:
- name: jwt-auth
- name: oidc-auth
config:
issuer: "https://auth.example.com"
skip_signature_validation: true
issuer_url: "https://auth.example.com"
audience: "my-api"
- name: opa-authz
config:
opa_url: "http://opa:8181/v1/data/authz/allow"
Expand Down Expand Up @@ -205,9 +205,10 @@ Two modes:

```yaml
x-barbacane-middlewares:
- name: jwt-auth
- name: oidc-auth
config:
issuer: "https://auth.example.com"
issuer_url: "https://auth.example.com"
audience: "my-api"
- name: cel
config:
expression: >
Expand Down Expand Up @@ -330,9 +331,10 @@ The `on_match.deny` action turns `cel` into a fully programmable gate — useful

```yaml
x-barbacane-middlewares:
- name: jwt-auth
- name: oidc-auth
config:
issuer: "https://auth.example.com"
issuer_url: "https://auth.example.com"
audience: "my-api"
- name: cel
config:
expression: >
Expand Down
13 changes: 8 additions & 5 deletions docs/guide/middlewares/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,18 @@ x-barbacane-middlewares:
paths:
/admin/users:
get:
security:
- bearerAuth: []
x-barbacane-middlewares:
- name: jwt-auth
- name: oidc-auth
config:
issuer: "https://auth.example.com"
issuer_url: "https://auth.example.com"
audience: "my-api"
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.internal"
# Resolved chain: correlation-id → cors → jwt-auth
# Resolved chain: correlation-id → cors → oidc-auth
```

**Name-based override.** When an operation entry has the same `name` as an entry in the global chain, **all** global entries with that name are dropped and the operation entries are appended in their declared order.
Expand Down Expand Up @@ -134,8 +137,8 @@ Middlewares can write and read a per-request key-value context. The chain's orde

```yaml
x-barbacane-middlewares:
- name: jwt-auth # writes context:auth.sub
config: { issuer: "https://auth.example.com" }
- name: oidc-auth # writes context:auth.sub
config: { issuer_url: "https://auth.example.com", audience: "my-api" }
- name: rate-limit # reads context:auth.sub
config:
quota: 100
Expand Down
22 changes: 13 additions & 9 deletions docs/guide/secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Use `env://` to reference environment variables:
x-barbacane-middlewares:
- name: oauth2-auth
config:
introspection_endpoint: https://auth.example.com/introspect
client_id: my-client
client_secret: "env://OAUTH2_CLIENT_SECRET"
```
Expand All @@ -34,9 +35,11 @@ Use `file://` to read secrets from files:

```yaml
x-barbacane-middlewares:
- name: jwt-auth
- name: oauth2-auth
config:
secret: "file:///etc/secrets/jwt-signing-key"
introspection_endpoint: https://auth.example.com/introspect
client_id: my-api-client
client_secret: "file:///etc/secrets/oauth2-client-secret"
```

The gateway reads the file content, trims whitespace, and uses the result. This works well with:
Expand Down Expand Up @@ -75,15 +78,16 @@ x-barbacane-dispatch:
Authorization: "Bearer env://UPSTREAM_API_KEY"
```

### JWT Auth with File-based Key
### S3 with Mounted Credentials

```yaml
x-barbacane-middlewares:
- name: jwt-auth
config:
public_key: "file:///var/run/secrets/jwt-public-key.pem"
issuer: https://auth.example.com
audience: my-api
x-barbacane-dispatch:
name: s3
config:
region: eu-west-1
bucket: assets
access_key_id: "env://AWS_ACCESS_KEY_ID"
secret_access_key: "file:///var/run/secrets/aws/secret-access-key"
```

### Multiple Secrets
Expand Down
38 changes: 29 additions & 9 deletions docs/guide/spec-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,17 +165,22 @@ Apply to a specific operation (runs after global middlewares):
paths:
/admin/users:
get:
security:
- bearerAuth: []
x-barbacane-middlewares:
- name: jwt-auth
- name: oidc-auth
config:
required: true
scopes: ["admin:read"]
issuer_url: "https://auth.example.com"
audience: "my-api"
required_scopes: "admin:read"
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.example.com"
```

An operation that runs an authentication middleware needs a `security` requirement naming a scheme from `components.securitySchemes`; without one the compiler stops with `E1057`. The [complete example](#complete-example) below declares `bearerAuth`.

### Middleware Merging

Operation middlewares are **merged** with global ones. If an operation middleware has the same name as a global one, the operation config overrides it. Non-overridden globals are preserved.
Expand Down Expand Up @@ -269,10 +274,13 @@ paths:
/orders:
post:
operationId: createOrder
security:
- bearerAuth: []
x-barbacane-middlewares:
- name: jwt-auth
- name: oidc-auth
config:
required: true
issuer_url: "https://auth.shop.example.com"
audience: "shop-api"
x-barbacane-dispatch:
name: http-upstream
config:
Expand All @@ -285,10 +293,14 @@ paths:
/orders/{orderId}/pay:
post:
operationId: payOrder
security:
- bearerAuth: []
x-barbacane-middlewares:
- name: jwt-auth
- name: oidc-auth
config:
required: true
issuer_url: "https://auth.shop.example.com"
audience: "shop-api"
required_scopes: "orders:pay"
x-barbacane-dispatch:
name: http-upstream
config:
Expand All @@ -298,6 +310,12 @@ paths:
responses:
"200":
description: Payment processed

components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
```

## AsyncAPI Support
Expand Down Expand Up @@ -392,10 +410,12 @@ operations:
action: send
channel:
$ref: '#/channels/events'
# Authenticated through the security scheme the server declares.
x-barbacane-middlewares:
- name: jwt-auth
- name: oidc-auth
config:
required: true
issuer_url: "https://auth.example.com"
audience: "events-api"
x-barbacane-dispatch:
name: kafka
config:
Expand Down
2 changes: 2 additions & 0 deletions docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,8 @@ Example config with secrets:
x-barbacane-middlewares:
- name: oauth2-auth
config:
introspection_endpoint: https://auth.example.com/introspect
client_id: my-api-client
client_secret: "env://OAUTH2_SECRET"
```

Expand Down
21 changes: 14 additions & 7 deletions docs/reference/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,14 @@ paths:
paths:
/admin:
get:
security:
- bearerAuth: []
x-barbacane-middlewares:
- name: jwt-auth
- name: oidc-auth
config:
required: true
scopes: ["admin:read"]
issuer_url: "https://auth.example.com"
audience: "my-api"
required_scopes: "admin:read"
x-barbacane-dispatch:
name: http-upstream
config:
Expand Down Expand Up @@ -392,14 +395,18 @@ paths:
```yaml
- name: jwt-auth
config:
required: true
header: Authorization
scheme: Bearer
issuer: https://auth.example.com
audience: my-api
scopes: ["read"]
groups_claim: roles # Optional: claim to read consumer groups from
public_key_jwk: # Key that verifies the token signature
kty: RSA
alg: RS256
n: "0vx7agoebGcQSuu..." # base64url modulus
e: AQAB
```

Reads the bearer token from `Authorization`. For keys published at a JWKS URL, use `oidc-auth`.

### rate-limit

```yaml
Expand Down
Loading