Problem 1
One parameter too many gets through
An unexpected header or parameter reaches the service.
Flexway's answer: Closed by default: an undeclared header, parameter, method or origin is refused.
Security
Tokens from several issuers, scopes and roles read from the contract, API keys and client certificates bound to a tenant: what is not declared does not pass.
11 of the 12 shown delivered · since v0.1.0
What you expect from this domain
external-callPartly · next to be scheduled

Problem 1
An unexpected header or parameter reaches the service.
Flexway's answer: Closed by default: an undeclared header, parameter, method or origin is refused.
Problem 2
Scopes and roles reimplemented service by service, with gaps.
Flexway's answer: Scopes and roles read from the contract's security and tags, checked once.
Problem 3
The tenant comes from a header the client controls.
Flexway's answer: The tenant is read from the verified identity; isolation is tested on every change.
Every step is a decision readable in the trace and in the console.
Security - Domain diagram: who calls, the decision steps, what is called, and where a request is refused.
identity refused: 401, 403
A caller holding an OIDC token: Flexway checks its signature, issuer, audience and scopes before any relay.
Routes through here
A caller holding an API key: the key is a first-class identity, bound to operations and to a tenant.
Routes through here
A caller authenticated by a client certificate (mTLS): the certificate carries the caller's identity and tenant.
Routes through here
A browser's origin is checked against the declared CORS policy; an undeclared origin gets 403.
Routes through here
Flexway checks who is calling (OIDC token, API key or client certificate) and reads the tenant from the identity; no valid identity: 401.
Routes through here
The token's issuer (iss) and audience (aud) are checked; several issuers can coexist.
Routes through here
The required scopes and roles come from the contract; a caller out of scope gets 403.
Routes through here
Parameters and body are validated against the contract's schema; a non-conforming request gets 422 without reaching the upstream.
Routes through here
Every authorization decision is logged in a chained, verifiable audit, without request content.
Routes through here
Your REST and gRPC services: they receive only the requests Flexway let through, under deadline and circuit breaker.
Routes through here
Deploy Flexway: topologies and the GitOps configuration cycle
The essentials of each topic, with its status in the published release; unfold a card for the full text.
JWTs from several issuers are checked on every request with cached keys, and opaque tokens through RFC 7662 introspection.
Flexway validates JWTs with JWKS keys discovered and cached in the background; key rotation happens with no restart and no wave of 401s. The issuer (iss) and audience (aud) are checked, and several issuers from different providers coexist in one configuration (auth.issuers). An issuer can accept several audiences for the duration of a rename. By default only asymmetric algorithms are accepted: none and HS* are refused.
Opaque tokens are checked through RFC 7662 introspection (opaque_tokens), with the same rules as a JWT and a response cached without exceeding its expiry; an unreachable provider gives 503. The gateway consumes identities, it does not issue them: the issuer remains your organisation's own.
Binding a token to its holder, through an mTLS certificate (RFC 8705) or DPoP proof of possession (RFC 9449), is upcoming; the choice between the two remains open.
The authentication requirement comes from the contract's security: no operation is served with a weaker requirement than the one declared.
The authentication requirement comes from the contract's security section, not from a separate table: scopes for oauth2 and openIdConnect, roles for http bearer, supplemented by x-flexway-scopes. An operation with no anonymous alternative requires an identity; tags carry no requirement. No operation is served with a weaker requirement than the one declared.
Roles are read from the claim named by roles_claim; without it, no role is satisfied. Refusals follow HTTP semantics - 401 when the identity is missing or fails verification, 403 when it is not sufficient - with WWW-Authenticate and an RFC 9457 body. Whether a resource belongs to a tenant is still checked by the service, the only one that knows its data.
What is not declared does not pass, and the body and parameters are validated against the contract's schema, with a 422 naming each field.
Whatever is not declared does not pass: an undeclared header is removed, an undeclared query parameter is refused by name, an undeclared method receives 405 with Allow, a non-allowed origin is refused. CORS is declared as a policy, global or per host, and security response headers are set on every response.
Body and parameters are validated against the contract schema: 422 naming each faulty field, with a code taken from the JSON Schema keyword and renamable (errors.field_codes). The body is read only if the operation declares one, within the server.limits.max_body bound (413 beyond). The mode is set per host or per operation (x-flexway-validation) - full, params or off - and the allow list of headers and parameters is kept in every mode.
No upstream error is relayed as is: gateway refusals follow RFC 9457, with a closed catalogue of codes and a request_id and trace_id in the response, the details staying in the log.
An API key or a client certificate remains possible, bounded by construction: bound to a tenant and to operations, never passed to the upstream.
When a caller can produce neither a workload identity nor an OAuth token, an API key remains possible, constrained by design. It is presented in a header only (Authorization: ApiKey), never in a URL parameter; an apiKey scheme placed elsewhere is refused at load. The store keeps only the SHA-256 fingerprint, compared in constant time, and the key exists in clear only once, at creation. Each key is bound to a tenant, to named operations and to a mandatory expiry.
Rotation keeps two active entries during the switchover; revocation means removing the entry, re-read by each replica on reload, with no restart. A stable prefix (fwk_) lets secret scanners spot a key published by mistake, and each call carries the key's identifier, never its value, in the trace and the log.
A client certificate is verified by the TLS listener (server.tls) or attested by the edge through x-forwarded-client-cert, trusted from a trusted peer only; it is bound to a tenant and to operations (auth.mtls.clients). The contract decides which mechanism satisfies which alternative: a token never replaces a key, nor the reverse. Neither the key nor the attested certificate reaches the upstream, and an API key remains an identity, not an authorisation.
The tenant comes from the verified identity, never from a client header, and counters and the authenticated cache are its own, with no sharing possible.
The tenant comes from the verified identity - the claim declared for the issuer (tenant_claim) - and never from a client-supplied header, which can be forged. The gateway writes it upstream under auth.tenant_header; an incoming tenant header is overwritten. Rate and quota counters are indexed by tenant, with no possible sharing.
Rate limiting counts per caller (issuer and subject, otherwise the client address behind server.trusted_proxies), never per calling pod: two users behind the same server-side client have separate counters. An authenticated response is cached only with a tenant and subject key, declared by the operation alone; without tenant and subject, nothing is cached.
This cache isolation is held by a blocking test run on every change, with a counter-test that strips the subject from the key. Cross-tenant access is treated as a critical vulnerability, not a defect.
Each authorisation decision can leave an audit line chained to the previous one, which makes a deletion or an alteration verifiable.
audit.decisions writes one authz_decision line per decision - all of them, or refusals only - with the operation, the path template, the hashed subject and the agent chain. Each line is chained to the previous one (seq, prev, hash) per replica, which makes deletion or tampering verifiable. The log holds no personal data in clear.
The rest of defence in depth lies in the product itself: distroless non-root image, read-only filesystem, SBOM, signature and attestation on the image digest, no native plugin and no script in the configuration. The administration surface sits on a separate port and accepts no key. A timestamped, correlated and verifiable audit helps you meet the logging and cybersecurity requirements that apply to your platform.
The identity-and-cors example, as it ships with Flexway v1.6.3.
# Two identity providers at once, the tenant from a signed claim, a browser application on its own
# origin. What each operation requires is in the contract, never here.
version: 1
contracts:
openapi: ./openapi.yaml
upstreams:
default:
url: http://orders.internal:8080
auth:
tenant_header: X-Tenant # written toward the upstream; a caller's value is overwritten
issuers:
- name: staff
discovery: https://id.example.com/realms/staff/.well-known/openid-configuration
audience: api
roles_claim: realm_access.roles
- name: customers
discovery: https://login.example.net/.well-known/openid-configuration
audience: api
tenant_claim: org
policies:
definitions:
browser:
type: cors
config:
allow_origins: ["https://app.example.com"]
allow_credentials: true
max_age: 10m
chains:
global: [browser]What is delivered in the published release v1.6.3, and what is coming; a feature is never shown as delivered before its release.
| Feature | Status |
|---|---|
| JWT validation, cached JWKS keys with rotation | Delivered · v0.1.0 |
| iss and aud checked; several issuers in one configuration | Delivered · v0.1.0 |
| Scopes and roles derived from the contract's security | Delivered · v0.1.0 |
| Closed by default: undeclared header, parameter, method or origin refused | Delivered · v0.1.0 |
| Body and parameters validated against the contract's schema | Delivered · v0.1.0 |
| API keys and client mTLS as first-class identities | Delivered · v0.1.0 |
| Opaque token introspection (RFC 7662) | Delivered · v0.1.0 |
| Chained audit log of authorisation decisions | Delivered · v0.1.0 |
| Sender-constrained tokens: mTLS (RFC 8705) or DPoP (RFC 9449) | Planned |
| Effective policy chain per route | Delivered · v0.1.0 |
| Local accounts and first admin, without an identity provider: generated initial password, forced change, TOTP for admins, shared lock | Delivered · v0.1.0 |
| Management of local accounts in the console: invitation, role and tenant, reset, MFA, deactivation | Delivered · v0.1.0 |
The other expectations of this domain
Flexwiz is a young company: you talk directly with the person who founds it. Tell us what you want to run through Flexway. We talk about your infrastructure and your digital sovereignty requirements.
Online booking is coming soon; until then, an e-mail is enough.