Skip to main content

OIDC browser authentication

Enable browser-based OpenID Connect authentication with encrypted session cookies.

Attaches to: Route

Note

Agentgateway supports more than one configuration style. Where a feature can also be configured in the simplified llm or mcp modes, the examples on this page show each option in tabs. For more information, see Routing-based configuration .

OIDC browser authentication provides built-in OpenID Connect login for browser-based clients. Unauthenticated requests are automatically redirected to the identity provider’s login page. After successful authentication, the user’s session is maintained with encrypted cookies.

The OIDC policy uses the OAuth 2.0 Authorization Code Flow with PKCE (Proof Key for Code Exchange) for secure browser-based authentication without requiring a separate proxy like oauth2-proxy.

About

The following diagram shows the OIDC browser authentication flow between the browser, agentgateway, and identity provider.

sequenceDiagram
autonumber
participant Browser
participant AGW as Agentgateway
participant IdP as Identity Provider

Browser->>AGW: Request protected resource
AGW->>AGW: No valid session cookie found
AGW->>Browser: 302 Redirect to IdP login<br/>(with PKCE code_challenge)
Browser->>IdP: Follow redirect to login page
IdP->>Browser: Display login form
Browser->>IdP: Submit credentials
IdP->>Browser: 302 Redirect to redirectURI<br/>(with authorization code)
Browser->>AGW: GET /oauth/callback?code=...
AGW->>IdP: Exchange code for ID token<br/>(with PKCE code_verifier)
IdP->>AGW: Return ID token
AGW->>AGW: Validate ID token with JWKS
AGW->>Browser: Set encrypted session cookie<br/>and redirect to original resource
Browser->>AGW: Request with session cookie
AGW->>AGW: Decrypt and validate cookie
AGW->>Browser: Return protected resource
  • Steps 1-3: Unauthenticated request. When a browser request arrives without a valid session cookie, the gateway redirects the user to the identity provider’s login page.
  • Steps 4-6: Login. The user authenticates with the identity provider.
  • Steps 7-8: Callback. After login, the identity provider redirects back to the redirectURI with an authorization code.
  • Steps 9-11: Token exchange. The gateway exchanges the authorization code for an ID token using PKCE.
  • Steps 12-15: Session cookie. The gateway sets an encrypted session cookie containing the ID token claims. Subsequent requests use this cookie.

Session management

Review the following details about session management.

  • Session cookies are encrypted and tamper-proof.
  • The gateway always requests the openid scope to obtain an ID token.
  • The gateway uses PKCE automatically to protect against authorization code interception.

Configuration

Add the oidc policy to a route to protect it with browser-based OIDC authentication.

Agentgateway requires the OIDC_COOKIE_SECRET environment variable to encrypt session cookies when an oidc policy is configured. Set it to a random value before you start the gateway, such as in the following example.

export OIDC_COOKIE_SECRET="$(python3 -c 'import os; print(os.urandom(32).hex())')"

# yaml-language-server: $schema=https://agentgateway.dev/schema/config
llm:
policies:
oidc:
issuer: http://localhost:7080/realms/agentgateway
clientId: agentgateway-browser
clientSecret: agentgateway-secret
redirectURI: http://localhost:3000/oauth/callback
scopes:
- profile
- email
models:
- name: "*"
provider: openAI
params:
apiKey: "$OPENAI_API_KEY"

# yaml-language-server: $schema=https://agentgateway.dev/schema/config
mcp:
port: 3000
policies:
oidc:
issuer: http://localhost:7080/realms/agentgateway
clientId: agentgateway-browser
clientSecret: agentgateway-secret
redirectURI: http://localhost:3000/oauth/callback
scopes:
- profile
- email
targets:
- name: everything
stdio:
cmd: npx
args: ["@modelcontextprotocol/server-everything"]

# yaml-language-server: $schema=https://agentgateway.dev/schema/config
gateways:
default:
port: 3000
routes:
- backends:
- host: localhost:18080
matches:
- path:
pathPrefix: /
policies:
oidc:
issuer: http://localhost:7080/realms/agentgateway
clientId: agentgateway-browser
clientSecret: agentgateway-secret
redirectURI: http://localhost:3000/oauth/callback
scopes:
- profile
- email

Keycloak example

Review the following example for a Keycloak IdP.

# yaml-language-server: $schema=https://agentgateway.dev/schema/config
llm:
policies:
oidc:
issuer: http://keycloak.example.com/realms/myrealm
clientId: agentgateway-browser
clientSecret: my-client-secret
redirectURI: http://localhost:3000/oauth/callback
scopes:
- profile
- email
models:
- name: "*"
provider: openAI
params:
apiKey: "$OPENAI_API_KEY"

# yaml-language-server: $schema=https://agentgateway.dev/schema/config
mcp:
port: 3000
policies:
oidc:
issuer: http://keycloak.example.com/realms/myrealm
clientId: agentgateway-browser
clientSecret: my-client-secret
redirectURI: http://localhost:3000/oauth/callback
scopes:
- profile
- email
targets:
- name: everything
stdio:
cmd: npx
args: ["@modelcontextprotocol/server-everything"]

# yaml-language-server: $schema=https://agentgateway.dev/schema/config
gateways:
default:
port: 3000
routes:
- backends:
- host: localhost:18080
matches:
- path:
pathPrefix: /
policies:
oidc:
issuer: http://keycloak.example.com/realms/myrealm
clientId: agentgateway-browser
clientSecret: my-client-secret
redirectURI: http://localhost:3000/oauth/callback
scopes:
- profile
- email

For a complete runnable setup, including a Compose file that starts a preconfigured local Keycloak instance, see the traffic-oidc example in the agentgateway repository.

config.yaml

frontendPolicies:
accessLog:
add:
user.id: jwt.sub
user.email: jwt.email
binds:
- port: 3000
listeners:
- name: default
protocol: HTTP
routes:
- name: app
matches:
- path:
pathPrefix: /
backends:
- host: localhost:18080
policies:
oidc:
issuer: http://localhost:7080/realms/agentgateway
clientId: agentgateway-browser
clientSecret: agentgateway-secret
redirectURI: http://localhost:3000/oauth/callback
scopes:
- profile
- email

Fields

Review the following table to understand this configuration.

FieldRequiredDescription
issuerYesOIDC provider issuer URL. Used for discovery and ID token validation.
clientIdYesOAuth2 client identifier registered with your identity provider.
clientSecretYesOAuth2 client secret for token exchange.
redirectURIYesAbsolute callback URI handled by the gateway, such as http://localhost:3000/oauth/callback.
scopesNoAdditional OAuth2 scopes to request. openid is always included automatically.
discoveryNoOverride the OIDC discovery document location. If omitted, uses ${issuer}/.well-known/openid-configuration.
authorizationEndpointNoExplicit authorization endpoint. Overrides the value from discovery.
tokenEndpointNoExplicit token endpoint. Overrides the value from discovery.
tokenEndpointAuthNoClient authentication method for the token endpoint. Discovery mode derives this from provider metadata. Explicit mode defaults to clientSecretBasic.
jwksNoJWKS source for ID token validation. If omitted, uses the jwks_uri from discovery.

Access log enrichment

After setting up OIDC browser authentication, you can use JWT claims from the OIDC session in access logs. Add a frontend policy such as the following example.

frontendPolicies:
accessLog:
add:
user.id: jwt.sub
user.email: jwt.email

Learn more