Skip to content
agentgateway has joined the Agentic AI FoundationLearn more

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Secure the UI

Page as Markdown

Require users to log in to the UI with an OIDC policy on the gateway that serves it.

About

To require users to authenticate, apply a browser OIDC policy to the gateway that serves the UI. Unauthenticated requests are redirected to your identity provider (IdP) to log in, and only requests that pass the policies in ui.policies reach the UI.

The ui.policies section takes the same policies that a route takes, so you can also use JWT, basic, or API key authentication for programmatic access. To restrict which authenticated users get in, add an authorization policy alongside the authentication policy.

Note

A policy in ui.policies applies only to the gateways that the ui section lists. It does not apply to the copy of the UI on the admin interface, which stays unauthenticated. That is safe by default, because the admin address is loopback-only, but it is a reason not to move it. For more information, see The UI and the admin interface are not the same thing.

Before you begin

  1. Install standalone agentgateway.
  2. Serve the UI on its own gateway. The examples on this page apply the OIDC policy to the ui-gateway on port 4001 that you created in that guide.
  3. Set up an IdP, such as Keycloak or Microsoft Entra ID. Consider creating a client specifically for the UI, such as agentgateway-ui. For provider-specific setup instructions, see the identity provider integrations.

Binary and Docker

  1. Set the OIDC_COOKIE_SECRET environment variable. Agentgateway requires this value to encrypt session cookies whenever an oidc policy is configured, and refuses to start without it. The key is an AES-256-GCM key, which is 32 random bytes encoded as 64 hexadecimal characters. It is a random value that you generate, not a value that your identity provider gives you.

    export OIDC_COOKIE_SECRET="$(openssl rand -hex 32)"
  2. Save the details of the UI client that you created in your IdP as environment variables. The redirect URI must match the address that you serve the UI on, and it must be registered as a valid redirect URI in your IdP. The following example uses a local address so that you can test the login flow first. When you expose the UI on a hostname, change this value to that hostname and register it in your IdP.

    export ISSUER_URL=https://keycloak.example.com/realms/agentgateway
    export UI_CLIENT_ID=agentgateway-ui
    export UI_CLIENT_SECRET=<client-secret>
    export REDIRECT_URI=http://localhost:4001/oauth/callback
  3. Add an oidc policy to the ui section of your configuration file. The following example redirects unauthenticated users on the ui-gateway to the OIDC provider to log in. The optional authorization policy further restricts access to users whose email address ends in @example.com.

    Agentgateway expands environment variables in the configuration file when it loads the file, so you can refer to the values that you exported in the previous step instead of writing the client secret into the file.

    # yaml-language-server: $schema=https://agentgateway.dev/schema/config
    gateways:
      default:
        port: 4000
      ui-gateway:
        port: 4001
    ui:
      gateways: [ui-gateway]
      policies:
        oidc:
          issuer: ${ISSUER_URL}
          clientId: ${UI_CLIENT_ID}
          clientSecret: ${UI_CLIENT_SECRET}
          redirectURI: ${REDIRECT_URI}
          scopes:
          - profile
          - email
        authorization:
          rules:
          - allow: jwt.email.endsWith("@example.com")

    Tip

    For the full list of oidc policy fields and a complete runnable Keycloak setup, see OIDC browser authentication and the traffic-unified-gateway example in the agentgateway repository.

  4. Start agentgateway with the updated config.

    agentgateway -f config.yaml
  5. Open the UI at the gateway’s address, such as http://localhost:4001/ui/. Instead of loading the UI directly, agentgateway redirects you to the OIDC provider to log in. After you authenticate, you are returned to the UI.

Helm

  1. Save the details of the UI client that you created in your IdP as environment variables. The redirect URI must match the address that you expose the UI on, and it must be registered as a valid redirect URI in your IdP. If you plan to expose the UI on a hostname, use that hostname now so that you do not have to register a second redirect URI later.

    export ISSUER_URL=https://keycloak.example.com/realms/agentgateway
    export UI_CLIENT_ID=agentgateway-ui
    export UI_CLIENT_SECRET=<client-secret>
    export REDIRECT_URI=https://agentgateway.example.com/oauth/callback
  2. Create a Secret that holds the session cookie encryption key and the OIDC client secret.

    After a user logs in, agentgateway keeps the session in a browser cookie that it encrypts with the session cookie encryption key. The key is a random value that you generate, not a value that your IdP gives you. Agentgateway requires an AES-256-GCM key, which is 32 random bytes that are encoded as 64 hexadecimal characters. Agentgateway refuses to start when an oidc policy is set and this key is missing or is not that length.

    kubectl create secret generic agentgateway-ui-secrets \
      -n agentgateway-system \
      --from-literal=OIDC_COOKIE_SECRET="$(openssl rand -hex 32)" \
      --from-literal=UI_CLIENT_SECRET="${UI_CLIENT_SECRET}"

    Note

    You choose the Secret’s name, and you pass it to the chart in the oidc.cookieSecretName value in the next step. However, the key within the Secret must be named OIDC_COOKIE_SECRET, because the chart reads that exact key. The client secret key can have any name, as long as the extraEnv entry that you add in the next step refers to the same name. This example keeps both values in one Secret, but you can also keep them in separate Secrets. In that case, set oidc.cookieSecretName to the Secret that holds the cookie key, and point the extraEnv entry at the Secret that holds the client secret.

  3. Add the OIDC policy to the ui section, point the chart at the Secret, and pass the client secret to the pod as an environment variable.

    The heredoc in this step is unquoted, so your shell substitutes the issuer, client ID, and redirect URI as it writes the file. The \$UI_CLIENT_SECRET reference is escaped, so it stays in the file as a literal $UI_CLIENT_SECRET that agentgateway resolves from the pod environment at startup. This way, the client secret stays in the Secret instead of the ConfigMap.

    cat <<EOF > values.yaml
    config:
      gateways:
        default:
          port: 4000
        ui-gateway:
          port: 4001
      ui:
        gateways: [ui-gateway]
        policies:
          oidc:
            issuer: ${ISSUER_URL}
            clientId: ${UI_CLIENT_ID}
            clientSecret: \$UI_CLIENT_SECRET
            redirectURI: ${REDIRECT_URI}
            scopes:
            - profile
            - email
      routes:
      - matches:
        - path:
            pathPrefix: /
        backends:
        - host: httpbin.httpbin.svc.cluster.local:8000
    oidc:
      cookieSecretName: agentgateway-ui-secrets
    extraEnv:
    - name: UI_CLIENT_SECRET
      valueFrom:
        secretKeyRef:
          name: agentgateway-ui-secrets
          key: UI_CLIENT_SECRET
    EOF
  4. Upgrade the release with your values file.

    helm upgrade -i agentgateway-standalone \
      oci://cr.agentgateway.dev/charts/agentgateway-standalone \
      --namespace agentgateway-system \
      --version v1.5.0 \
      --reuse-values \
      -f values.yaml
  5. Confirm that the pod is running.

    kubectl get pods -n agentgateway-system \
      -l app.kubernetes.io/name=agentgateway-standalone
  6. Port-forward the UI port again, and confirm that an unauthenticated request is redirected to your IdP.

    kubectl port-forward -n agentgateway-system \
      deploy/agentgateway-standalone 4001:4001
    curl -s -o /dev/null -D- http://localhost:4001/ui | grep -i location

    Example output:

    location: https://keycloak.example.com/realms/agentgateway/protocol/openid-connect/auth?response_type=code&client_id=agentgateway-ui&...

Important

Agentgateway fetches the OIDC discovery document at startup, so the issuer must be reachable from the pod. When the fetch fails, the pod does not start, and the logs report failed to decode oidc discovery response from uri. If the pod enters CrashLoopBackOff after you add the policy, check the issuer URL and any egress restrictions.

Next steps

Was this page helpful?
Agentgateway assistant

Ask me anything about agentgateway configuration, features, or usage.

Note: AI-generated content might contain errors; please verify and test all returned information.

Tip: one topic per conversation gives the best results. Use the + button in the chat header to start a new conversation.

Switching topics? Starting a new conversation improves accuracy.
↑↓ navigate select esc dismiss

What could be improved?

Your feedback helps us improve assistant answers and identify docs gaps we should fix.

Need more help? Join us on Discord: https://discord.gg/y9efgEmppm

Want to use your own agent? Add the Solo MCP server to query our docs directly. Get started here: https://search.solo.io/.