Breadcrumb

  1. Red Hat Interactive Learning Portal
  2. Unlock self-service API credentials on Connectivity Link
  3. Protect AI inference APIs with OpenID Connect AuthPolicy

Unlock self-service API credentials on Connectivity Link

Understand how to set up a hub-only Connectivity Link stack, then let developers mint API keys and OIDC client credentials from Red Hat Developer Hub, without ticket back and forth.

API-only inference endpoints accept Bearer tokens instead of interactive login redirects. This lesson protects the Computer Vision API (neuroface-cv) with Kuadrant AuthPolicy JSON Web Token (JWT) validation and lets developers provision OpenID Connect (OIDC) clients from Developer Hub. On the hub-only install from Lesson 1, inference runs locally on the hub. Traffic flows through neuroface-gateway to the neuroface-cv back end without Skupper or spoke clusters.

Prerequisites:

In this lesson, you will:

  • Understand why AuthPolicy with JWT beats OIDCPolicy for API-only workloads.
  • Provision OIDC clients from a Developer Hub software template.
  • Apply AuthPolicy JWT validation and plan-based RateLimitPolicy.
  • Validate tokens from Swagger Try it out and curl.
  • Revoke OIDC clients through a companion self-service template.

Why AuthPolicy instead of OIDCPolicy

This table gives you scenarios and why to use AuthPolicy instead of an OIDCPolicy.

Scenario

Policy

Why

Web application with login redirect

OIDCPolicy

User completes interactive login; Gateway stores session cookies

Programmatic API / Swagger client credentials

AuthPolicy with JWT

Client sends Authorization: Bearer; no redirect required

The AI Computer Vision API is an inference endpoint. Clients obtain a JWT from Keycloak and send it on every request. An OIDCPolicy redirect breaks Swagger UI and machine-to-machine callers. Figure 1 illustrates the OIDC client credentials path from Developer Hub and Keycloak through AuthPolicy to the Computer Vision API.

OIDC flow: Developer Hub provisions Keycloak cv client; JWT validated by neuroface-cv AuthPolicy before YOLO PPE.
Figure 1: End-to-end OIDC client credentials flow.

A developer runs the self-service template in Developer Hub, receives client credentials from Keycloak realm cv, obtains a JWT, and calls the Computer Vision API through a gateway protected by AuthPolicy.

A hub-only traffic path looks something like this:

Client (Swagger / curl)
 → neuroface-cv.<apps-domain>
 → Gateway neuroface-gateway
 → HTTPRoute neuroface-cv-lb
 → AuthPolicy authpolicy-cv (JWT validation)
 → RateLimitPolicy neuroface-cv-ratelimit (plan tier)
 → Backend neuroface-cv (YOLO PPE on hub)

The AuthPolicy belongs on that Gateway hop because this API is machine-to-machine. Clients already have a JWT from Keycloak and send it as Authorization: Bearer. The AuthPolicy validates that token before the request reaches neuroface-cv, so Swagger and curl work without a login redirect. An OIDCPolicy would send those callers through interactive login and break this path. The you only look once (YOLO) service stays focused on inference; identity is enforced at the gateway. 

Review Keycloak realm cv

You do not configure this realm by hand in this lesson. The Pattern custom resource from the install lesson already imported realm cv through the Keycloak Operator. A backstage-provisioner confidential service account lets Developer Hub create and delete OIDC clients through the Admin REST API. Vault stores the provisioner secret, and External Secrets Operator synchronizes it into Keycloak and Developer Hub as KEYCLOAK_PROVISIONER_BASIC_AUTH, so credentials stay out of Git-tracked ConfigMaps.

Provision OIDC clients from Developer Hub

Figure 2 shows the OIDC credentials self-service form for Keycloak realm cv. You can specify your target API, set a client label, select the Client credentials (M2M) as the grant type, and select the plan tier, such as Free.

OIDC form with neuroface-cv-openapi target, client label team-d, and client_credentials grant type.
Figure 2: OIDC client request.

Figure 3 shows the one-time scaffolder task result with client ID, secret, and token endpoint. Copy these OIDC credentials, as these are shown only once.

Scaffolder output with OIDC client ID, secret, Keycloak token URL, and client_credentials curl.
Figure 3: Task result.

Apply AuthPolicy for JWT validation

For realm cv, the chart sets redirectAuth: false, which renders an AuthPolicy instead of an OIDCPolicy. Here is an example of the AuthPolicy Custom Resource (CR) file:

apiVersion: kuadrant.io/v1
kind: AuthPolicy
metadata:
  name: authpolicy-cv
  namespace: neuroface-gateway-system
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: neuroface-cv-lb
  when:
  - predicate: request.method != "OPTIONS"
  rules:
    authentication:
      jwt-users:
        jwt:
          issuerUrl: "https://keycloak.<apps-domain>/realms/cv"
    response:
      success:
        headers:
          x-auth-client-id:
            plain:
              expression: "has(auth.identity.client_id) ? auth.identity.client_id : auth.identity.azp"

The issuerUrl must match the issuer claim token in Keycloak exactly. Keycloak's canonical hostname is keycloak.<apps-domain>.

The spec.when section exempts OPTIONS from JWT validation so Cross-Origin Resource Sharing (CORS) preflight can succeed. If Swagger Try it out still fails after HTTPRoute CORS headers and this AuthPolicy exemption, then see the next lesson, Use the Swagger Try It Out feature for Connectivity Link with EnvoyFilter for more details.

Rate limit by JWT plan claim

The self-service template injects a plan claim into each client's tokens. A RateLimitPolicy on the same HTTPRoute enforces tier limits on /v1/predict:

apiVersion: kuadrant.io/v1
kind: RateLimitPolicy
metadata:
  name: neuroface-cv-ratelimit
spec:
  targetRef:
    kind: HTTPRoute
    name: neuroface-cv-lb
  limits:
    predict-free:
      when:
      - predicate: 'request.path.matches("^/v1/predict")'
      - predicate: 'has(auth.identity) && has(auth.identity.plan) && auth.identity.plan == "free"'
      counters:
      - expression: auth.identity.sub
      rates:
      - limit: 100
        window: 1h
    predict-gold:
      when:
      - predicate: 'request.path.matches("^/v1/predict")'
      - predicate: 'has(auth.identity) && has(auth.identity.plan) && auth.identity.plan == "gold"'
      counters:
      - expression: auth.identity.sub
      rates:
      - limit: 500
        window: 1h

Test from Swagger and curl

Next, it is time to test out the policy being implemented correctly. Figure 4 shows an unauthenticated Swagger Try it out on GET /health returning HTTP 401.

Swagger HTTP 401 Unauthorized for GET /health when no Bearer token is supplied.
Figure 4: Unauthenticated Try it out on GET /health returns HTTP 401, confirming AuthPolicy enforcement at the Gateway.

Figure 5 shows a successful Swagger Try it out on GET /health with a Bearer JWT returning HTTP 200. The AuthPolicy validates the token; the Gateway returns model metadata from the Computer Vision backend.

Swagger HTTP 200 JSON with status ok, model_name yolo-ppe, and model_loaded true after JWT auth.
Figure 5: Successful Try it out on GET /health with a Bearer JWT.

From the terminal:

export CLUSTER_DOMAIN="apps.<your-cluster-domain>"
export CLIENT_ID="client-neuroface-cv-openapi-my-app"
export CLIENT_SECRET="<secret-from-template>"

TOKEN=$(curl -sk -X POST \
 "https://keycloak.${CLUSTER_DOMAIN}/realms/cv/protocol/openid-connect/token" \
 -d "grant_type=client_credentials" \
 -d "client_id=${CLIENT_ID}" \
 -d "client_secret=${CLIENT_SECRET}" \
 | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

curl -sk -H "Authorization: Bearer ${TOKEN}" \
 "https://neuroface-cv.${CLUSTER_DOMAIN}/health"

Expected output:

{"status": "ok", "model_name": "yolo-ppe", "model_loaded": true}

Revoke OIDC clients

Revoke the OIDC client when it should no longer mint JWTs. For example, when a team member leaves, a secret leaks, or you finish the lab. The create template only provisions the client; until you revoke it, that client remains valid in realm cv. Use the Revoke OIDC client (Keycloak cv) self-service template with the same target API and client label used at creation time. 

To verify, open the Keycloak Admin Console, select the Computer Vision realm (cv) from the realm dropdown, then open Clients in the left menu. Confirm the revoked client no longer appears in the list, for example, client-neuroface-cv-openapi-team-d. After revocation, the OIDC client no longer appears in this list.

Figure 6 shows the Clients list in realm Computer Vision (cv) after revocation.

Keycloak Admin Console with Computer Vision realm selected and Clients open in the left menu; the revoked OpenID Connect client is no longer listed.
Figure 6. Keycloak Admin Console.

NeuroFace demo

The Swagger and curl checks prove AuthPolicy on /health. NeuroFace is the application that consumes the Computer Vision API, and it calls /v1/predict through the same gateway. Run the demo to confirm a real client, not only Swagger, can use the JWT-protected path for inference. Figure 7 shows the NeuroFace Personal Protective Equipment (PPE) Safety Detection demo calling the protected Computer Vision Gateway.

NeuroFace PPE UI with person box, missing hardhat and vest alerts, and Granite LLM analysis.
Figure 7: NeuroFace mobile demo. Real-time PPE detection via the protected CV gateway (/v1/predict).

AuthPolicy vs OIDCPolicy decision guide

Use this table when you choose how Connectivity Link authenticates callers. Pick an OIDCPolicy when a person logs in to the browser and the gateway keeps a session. Pick AuthPolicy with JWT when a machine or Swagger client already has a token and sends Authorization: Bearer on every request, as with this Computer Vision API. 

Requirement

Use

Human login in browser

OIDCPolicy + redirect

M2M / Swagger client credentials

AuthPolicy + JWT

CORS preflight from Swagger

AuthPolicy with when: OPTIONS exempt

Session cookies after login

OIDCPolicy

Now that NeuroFace has been successfully demonstrated, it’s time to make Swagger work on Connectivity Link with EnvoyFilter. 

Previous resource
Provision self-service API keys for external REST APIs
Next resource
Use the Swagger Try It Out feature for Connectivity Link with EnvoyFilter