JWT Authentication

This guide shows how to enforce client authentication with JSON Web Tokens (JWTs) in Airlock Microgateway. Microgateway retrieves a JWT from the request, validates it using the configured JWKS and JWT settings, and then applies access control rules (optionally including claim checks).

JWT authentication is configured by connecting these resources:

  • JWKS: provides the public keys used to verify the JWT signature (either from a local Secret or a remote JWKS endpoint).
  • JWT: defines where the token is extracted from and what makes a token acceptable (JWKS, issuer, audiences, subject, lifetime constraints).
  • AccessControlPolicy: attaches to an HTTPRoute, enforces JWT authentication via authentication.jwt.jwtRef, and optionally authorizes requests based on JWT claims.

Prerequisites

  • A Gateway Deployment.
  • An HTTPRoute routing traffic to your application/API (JWT authentication is attached via AccessControlPolicy.spec.targetRefs[].HTTPRoute).
  • A JWT issuer that provides tokens and exposes signing keys (e.g., via a JWKS endpoint), or signing keys available as a local JWKS file.

Configuration

Create a JWKS resource

Create a JWKS CR that provides the keys used to verify JWT signatures. You can source JWKS either:

  • from a local Secret (key jwks.json), or
  • from a remote endpoint (spec.provider.remote.uri) with optional TLS verification settings and timeouts.
  •  
    Risk

    Disabling certificate verification for a remote JWKS endpoint is insecure.

    • In production, always use certificate verification; disable it only for testing.

Example with remote JWKS endpoint:

 
Example
apiVersion: microgateway.airlock.com/v1alpha1
kind: JWKS
metadata:
  name: <your-jwks-name>
  namespace: <your-namespace>
spec:
  provider:
    remote:
      uri: "https://<your-jwks-host>/<your-jwks-path>"
      timeouts:
        connect: 1s
      tls:
        certificateVerification:
          publicCAs: {}

Create a JWT resource

Create a JWT CR. It defines:

  • Extraction sources (spec.extractionSources):
    • This configures the locations Microgateway uses to retrieve the JWT, which is extracted from the first source (in list order) that is present. If extractionSources is not specified, Microgateway extracts the JWT from the Authorization: Bearer ... header.
  • Acceptance requirements (spec.requireAny)
    • At least one requirement entry must be satisfied. A JWT satisfies an entry if it can be verified by the entry’s JWKS and matches the configured constraints (e.g., issuer and audiences).
    • At least one requirement entry must be satisfied. A JWT satisfies an entry if it is verifiable by the entry’s jwksRef and matches all additional specified matchers (e.g., issuer, audiences, and subject).
  • Time constraints:
    • expirationRequired controls whether the exp claim is mandatory. If expirationRequired is true and exp is missing or invalid, JWT validation fails.
    • maxLifetime limits the JWT lifetime (exp/nbf or exp-iat). JWTs that are missing the required claims become invalid.
    • clockSkewTolerance allows limited clock skew when validating exp and nbf.

Example:

 
Example
apiVersion: microgateway.airlock.com/v1alpha1
kind: JWT
metadata:
  name: <your-jwt-config-name>
  namespace: <your-namespace>
spec:
  extractionSources:
    - bearerToken: {}
    # Optional: extract from a cookie (example name)
    - cookie:
        name: <your-cookie-name>
  requireAny:
    - jwksRef:
        name: <your-jwks-name>
      issuer: "<your-issuer>"
      audiences:
        - "<your-audience>"
      subject:
        matcher:
          # Choose one matcher type that fits your subject format
          prefix: "<your-subject-prefix>"
          # exact: "<your-subject>"
  expirationRequired: true
  maxLifetime: 24h
  clockSkewTolerance: 10s

Create an AccessControlPolicy resource to enforce JWT authentication

Attach an AccessControlPolicy to your HTTPRoute and configure the following settings:

  • authentication.jwt.jwtRef.name to select the JWT configuration to apply.
  • Optional claim-based authorization under authorization.requireAll/authorization.requireAny using jwt.claim matchers.

Note that claim value matching is only supported for primitive types (or arrays of primitives). Unsupported claim types (e.g., objects) never match.

Example

 
Example
apiVersion: microgateway.airlock.com/v1alpha1
kind: AccessControlPolicy
metadata:
  name: <your-acp-name>
  namespace: <your-namespace>
spec:
  targetRefs:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      name: <your-httproute-name>
  policies:
    - requestConditions:
        path:
          matcher:
            prefix: /api
      authorization:
        requireAll:
          - jwt:
              claim:
                name: sub
                value:
                  matcher:
                    prefix: "<your-required-sub-prefix>"
        authentication:
          jwt:
            jwtRef:
              name: <your-jwt-config-name>
    - authorization:
        deny: {}

Validation

  1. Send a request without a JWT to a protected path (e.g., /api/...).
    • Expected result:
      The request is rejected according to your policy configuration.
  2. Send a request with a JWT that satisfies the configured requirements (JWKS verification plus issuer/audience/subject match and time constraints).
    • Expected result:
      The request passes authentication, and (if configured) claim-based authorization grants access.

Troubleshooting

If the provided JWKS is invalid (e.g., due to syntax errors), the following will occur:

  • Microgateway Engine logs an error in the application log.
  • JWT validation fails.
  • Requests are blocked.

CR reference documentation