Lua ยท Kong 3.x
Working
Kong API Gateway with Custom RBAC and JWT Plugins
Two Lua plugins that move access policy out of every service and into the gateway
Both plugins ported from Kong 2.x to 3.x, running DB-less
Overview
Every service behind a gateway ends up re-implementing the same two checks: is this token real, and is this caller allowed to call this route. Doing it per service means the answer drifts. These two Kong plugins move both checks to the one place every request already passes through.
The first is a JWT validator that caches JWKS from the identity provider at runtime, so key rotation needs no redeploy. The second is an RBAC authorizer that resolves roles from JWT claims through an 8-stage precedence pipeline, which is what makes overlapping rules deterministic instead of order-dependent.
Access policy ships as declarative config through a pattern DSL for endpoint rules, with method wildcards and inverted role matching, so a new rule is a config change rather than a plugin change. Both plugins were then ported from Kong 2.x to 3.x and run against the gateway in DB-less mode.
Stack
- Gateway
- Kong 3.x, DB-less declarative config
- Plugins
- Lua, two custom plugins
- Token validation
- OIDC with runtime JWKS caching
- Identity providers
- Keycloak and Zitadel
- Local environment
- Docker
Decisions Worth Explaining
An 8-stage precedence pipeline instead of first-match
Role rules overlap in practice: a wildcard on a path, a specific method, an inverted exclusion. First-match makes the outcome depend on config order, which is invisible in review. Explicit precedence stages make the resolved decision the same regardless of how the rules were written down.
JWKS cached at runtime, not baked into config
Pinning provider keys into gateway config means every key rotation is a deploy. Fetching and caching JWKS at runtime keeps rotation a provider-side operation.
A pattern DSL rather than one rule per endpoint
Method wildcards and inverted role matching keep the rule count proportional to the policy, not to the number of routes.
What Is Not Done
- No published benchmark of the added per-request latency from the RBAC pipeline.
- The precedence pipeline has no automated test matrix covering all 8 stages.