Authentication
Per-rule authentication and authorization from a plain Secret: OIDC, SAML, LDAP and JWT providers with stateless sessions.
krouter authenticates requests per route rule, through the same
ExtensionRef filter mechanism as rate limiting and
the WAF. Because the configuration carries credentials (client secrets,
bind passwords, signing keys), it lives in a
Secret
rather than a ConfigMap, under the single key auth.hcl. The Secret
lives in the route’s own namespace, and the filter and the Secret it
points to always travel together:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app
namespace: shop
spec:
parentRefs:
- name: public
rules:
- matches:
- path:
type: PathPrefix
value: /app
filters:
- type: ExtensionRef
extensionRef:
group: ""
kind: Secret
name: app-auth
backendRefs:
- name: app
port: 8080
---
apiVersion: v1
kind: Secret
metadata:
name: app-auth
namespace: shop
stringData:
auth.hcl: |
version = 1
auth {
session {
secret = "a-random-string-of-at-least-32-bytes"
lifetime = "12h"
}
provider "oidc" {
issuer = "https://idp.example.com"
client_id = "shop-app"
client_secret = "..."
scopes = ["openid", "profile", "email"]
}
}
An auth.hcl key in a ConfigMap, or a ratelimit.hcl/waf.hcl key in a
Secret, is invalid: each key belongs to exactly one kind, and a misplaced
key rejects the reference.
Providers
An auth block configures one or more provider blocks, at most one per
type. A request is authenticated by the first applicable source: a valid
session cookie, then a
Bearer token (jwt),
then Basic credentials
(ldap). Unauthenticated browser navigations are redirected to the login
page; everything else receives 401 with one challenge per credential
provider.
provider "oidc"
OpenID Connect authorization code flow with PKCE, for browser users:
issuer: discovery base URL; the endpoints and JWKS are read from<issuer>/.well-known/openid-configuration.client_idandclient_secret: the client registered at the provider.scopes: requested scopes (includeopenid).- Refresh tokens, when granted, ride the session cookie and renew the session transparently; a refresh rejected by the provider sends the user back through login.
provider "saml"
SAML 2.0 service provider, SP-initiated only:
entity_id: this service provider’s entity ID.idp_metadata_urlor inlineidp_metadata: the identity provider’s metadata document.sp_keyandsp_certificate: PEM material used to sign authentication and logout requests. The SP metadata is published on the reservedsaml/metadataendpoint for registration at the IdP.attributes: maps assertion attribute names ontoemailandgroups.- Unsolicited (IdP-initiated) responses are rejected; front-channel single logout is supported in both directions.
provider "ldap"
Directory-backed credentials, serving browsers through the login form and API clients through HTTP Basic:
url(ldap://orldaps://), with optionalstart_tlsand acaPEM bundle for the directory’s certificate.bind_dnandbind_password: the service account used to search.user_base_dnanduser_filter: search-then-bind resolution, with{username}substituted (and escaped) in the filter.realm: the Basic challenge realm.attributesmaps directory attributes ontoemailandgroups; an optionalgroup_searchblock (base_dn,filterwith{dn},attribute) collects groups from group entries instead.- A valid session always outranks resent Basic credentials, so API clients do not trigger a directory bind on every request.
provider "jwt"
Pre-issued bearer tokens, for machine-to-machine calls:
issuerandaudiences: required claim values.jwks_url: the key set used to verify signatures; only asymmetric algorithms are accepted.jwtneeds no session and no cookies. It is also the only provider usable on GRPCRoute rules: gRPC clients cannot follow interactive logins.
Interactive providers (oidc, saml, ldap) accept an optional
display_name shown on the login page.
Sessions and the login page
Any interactive provider requires a session block:
secret(at least 32 bytes) keys the cookie encryption;lifetimedefaults to12h.- Sessions are stateless: an encrypted, authenticated cookie holds the identity, so any data-plane pod can validate it without shared storage and sessions survive configuration reloads. Changing the secret invalidates every session at once.
Each extension reserves a path prefix (path_prefix, defaulting to
/.krouter/auth) on the hostnames its rules serve. It shadows user
routes and hosts the login page (login, a chooser when several
interactive providers are configured), the provider endpoints
(oidc/start, oidc/callback, saml/start, saml/acs,
saml/metadata, saml/slo, ldap/login) and logout, which clears
the session and, for SAML, initiates single logout at the IdP.
Authorization
An optional authorization block restricts authenticated identities:
authorization {
require {
claim = "groups"
values = ["admins", "operators"]
}
}
Every require block must be satisfied (the claim holds at least one of
the listed values). An authenticated identity failing authorization
receives 403, never a login redirect.
Composition and status
Several auth Secrets on one rule merge in filter list order, like
rate-limit documents: session and same-type provider blocks merge
attribute by attribute, require blocks concatenate (a later Secret can
only tighten authorization), and path_prefix is overridden. The ordered
list of referenced Secrets identifies the extension, and the session
cookie name derives from it: rules referencing the same Secrets in the
same order share sessions.
The control plane validates the merged configuration statically (at least
one provider, at most one per type, session material present when an
interactive provider is, key material well-formed) without ever calling
the identity provider. A broken reference follows the same fail-closed
contract as other extensions: the route stays accepted, ResolvedRefs
turns False with reason InvalidExtensionRef, and matching requests
are answered 500.
Enforcement order and outcomes
Authentication runs after rate limiting and before the WAF, so unauthenticated traffic never consumes WAF CPU. CORS preflights are exempt from authentication only (browsers send them without credentials); every other request on the rule is enforced:
| Outcome | Response |
|---|---|
| Authenticated and authorized | Forwarded, with identity headers |
| No credentials, browser navigation, interactive provider | 302 to the login page |
| No credentials, anything else | 401 with a challenge per credential provider |
| Presented but invalid credentials | 401, never a redirect |
| Authenticated but not authorized | 403 |
| Broken extension reference | 500 |
| Identity provider unreachable | 503, fail closed (established sessions keep working) |
Forwarded requests carry the identity in X-Auth-Request-User,
X-Auth-Request-Email and X-Auth-Request-Groups; inbound values of
these headers are stripped on authenticated rules, so backends can trust
them.
See Observability for the decision metric and the access-log fields recording authentication outcomes, and the authentication tutorial for a hands-on walkthrough from a login form to bearer tokens.