AuthGeek Demo
Gateway Pattern — Apache APISIX + Keycloak (native OIDC)

Live Gateway: Real JWT Verification

APISIX's native openid-connect plugin verifies every request's JWT signature against Keycloak's live JWKS, injects user-context headers, and calls OPA for the tier decision — all without the backend knowing any auth logic exists. Log in below and fire live requests through the gateway.

Apache APISIX Keycloak RS256 JWT (JWKS) OPA Policy Header Injection Enterprise IDP Federation
Auth flow — once, at login

Browser sends credentials directly to Keycloak (Direct Grant / ROPC) and gets back a signed RS256 JWT, which the browser keeps. This is the gateway pattern's tradeoff — the token lives in the browser. See the BFF pattern demo for the alternative, where it never leaves the server.

API request flow — every call

Browser sends Authorization: Bearer <jwt> to APISIX. Its openid-connect plugin verifies the signature against Keycloak's JWKS (no fake string matching — a real cryptographic check), then injects x-user-id, x-user-tier, calls OPA for tier enforcement — all before the request reaches the backend.

Checking session…

Architecture Review Q&A

Q: Does JWT validation or the OPA call expose us to DDoS attacks on Keycloak?

No. APISIX evaluates plugins in a fixed order to prevent resource exhaustion attacks.

  • 1. No IDP round-trip per request: the openid-connect plugin verifies the RS256 signature against a JWKS cached at discovery time. It does not call Keycloak to introspect the token on every request. If the signature is invalid or expired, it's rejected immediately (401) before OPA is ever called.
  • 2. OPA only sees verified requests: the gateway's opa plugin runs after JWT verification — forged tokens never reach OPA at all.
  • 3. L3/L4 protection: a CDN/tunnel in front of the gateway drops raw volumetric attacks before they reach APISIX.

Q: How do we trigger MFA programmatically? Who determines when it's needed?

It's decoupled. The API backend doesn't trigger MFA, and the gateway doesn't hardcode MFA rules.

  • 1. OPA decision: Open Policy Agent evaluates the endpoint sensitivity against the user's current token claims. If the user needs a higher Level of Assurance (LOA), OPA returns a structured denial with `require_step_up: true` and the target tier.
  • 2. Gateway enforcement: APISIX's opa plugin reads OPA's response and returns a `403 Forbidden` containing the `step_up_required` hint in the JSON envelope.
  • 3. Client action: the frontend intercepts the `403`. Seeing `step_up_required`, it redirects the user to Keycloak with `acr_values=loa3` to force an MFA prompt.

Q: Are there other enterprise patterns (M2M, On-Behalf-Of) supported by this architecture?

Yes. The gateway handles Service-to-Service (M2M) authentication (Client Credentials) exactly the same way through standard JWT validation. It also supports Asynchronous Event triggering (On-Behalf-Of auditing) using injected headers.

Read the comprehensive Gateway Patterns Guide →

The honest trade-off
What it costs
The verified JWT ends up in the browser (localStorage in this demo). It's simple and stateless, but a token in the browser is a credential one XSS away from theft, and there's no server-side switch to revoke it before it expires.
When you'd choose differently
Reach for the BFF pattern when XSS is a realistic threat, you need instant revocation, or compliance dictates tokens never touch the client. Reach for the sidecar pattern when you want authorization decided next to each workload rather than at a shared gateway.