About
A SAML 2.0 Service Provider (SP) HTTP filter that adds browser-based single sign-on authentication to any service behind Envoy Proxy.
Features
- SP-Initiated SSO: Redirects unauthenticated users to your Identity Provider
- Assertion Validation: Full SAML Response signature verification and condition checks
- Session Management: HMAC-signed cookies with configurable expiration
- Attribute Forwarding: Maps SAML attributes to upstream request headers
- SP Metadata Endpoint: Auto-generated metadata XML for easy IdP registration
- Signed AuthnRequests: Optional RSA-SHA256 signing of outbound authentication requests
- Auto-Generated SP Certificates: Ephemeral keypair generated when no certificate is provided
How It Works
The filter intercepts incoming HTTP requests and checks for a valid session cookie. If no session exists, the browser is redirected to the configured IdP with a SAML AuthnRequest. After authentication, the IdP POSTs a SAMLResponse to the Assertion Consumer Service (ACS) endpoint. The filter validates the assertion, creates a signed session cookie, and redirects the user to their original URL. Subsequent requests include the session cookie and pass through with identity headers set.
Configuration
Required fields:
entity_id: The SP entity ID (usually, audience URI)acs_path: Path for the Assertion Consumer Service endpointidp_metadata_xml: IdP metadata XML, as{"inline": "<xml>..."}or{"file": "/path/to/metadata.xml"}
Optional fields:
sp_cert_pem/sp_key_pem: PEM-encoded SP certificate and private key, each as{"inline": "..."}or{"file": "/path/to/file.pem"}. If both are omitted, an ephemeral self-signed keypair is auto-generated — convenient for development or when the IdP does not require a pre-registered SP certificate. If provided, both must be set together.- Session settings:
session.duration,session.cookie_name,session.cookie_secure,session.cookie_domain,session.cookie_signing_key bypass_paths,attribute_headers,sign_authn_requests,default_redirect_path
Metrics
The extension emits the following Envoy counters:
| Metric | Type | Tags | Description |
|---|---|---|---|
saml_authn_requests_total |
Counter | - | Incremented on each IdP redirect |
saml_assertions_validated_total |
Counter | result (success / failure) |
Incremented after SAML response validation |
saml_sessions_created_total |
Counter | - | Incremented on successful ACS processing |
saml_sessions_validated_total |
Counter | result (valid / expired / invalid) |
Incremented on session cookie validation |
Usage Examples
Basic SAML SSO
Minimal setup - only the IdP metadata is needed. An ephemeral SP certificate and key are auto-generated.
# Start keycloack
curl -o docker-compose.yaml https://raw.githubusercontent.com/tetratelabs/built-on-envoy/refs/heads/main/extensions/composer/saml/demo/keycloak/docker-compose-remote.yaml
docker compose -f docker-compose.yaml up --wait
# Download the IdP metadata
curl http://localhost:8080/realms/saml-demo/protocol/saml/descriptor -o idp-metadata.xml
# Run the plugin
boe run --extension saml --config '
{
"entity_id": "http://localhost:10000",
"acs_path": "/saml/acs",
"idp_metadata_xml": {"file": "idp-metadata.xml"}
}'
# Test the plugin in the browser and login as testuser/testpass
open http://localhost:10000
# Cleanup keycloak
docker compose -f docker-compose.yaml down -v Explicit SP Certificate
Provide your own SP certificate and key for production deployments where the IdP requires a pre-registered SP certificate.
# Start keycloack
curl -o docker-compose.yaml https://raw.githubusercontent.com/tetratelabs/built-on-envoy/refs/heads/main/extensions/composer/saml/demo/keycloak/docker-compose-remote.yaml
docker compose -f docker-compose.yaml up --wait
# Download the IdP metadata
curl http://localhost:8080/realms/saml-demo/protocol/saml/descriptor -o idp-metadata.xml
# Run the plugin
boe run --extension saml --config '
{
"entity_id": "http://localhost:10000",
"acs_path": "/saml/acs",
"idp_metadata_xml": {"file": "idp-metadata.xml"},
"sp_cert_pem": {"file": "sp-cert.pem"},
"sp_key_pem": {"file": "sp-key.pem"}
}'
# Test the plugin in the browser and login as testuser/testpass
open http://localhost:10000
# Cleanup keycloak
docker compose -f docker-compose.yaml down -v Custom Session Settings
Configure session cookie name, duration, domain, security, and a fixed HMAC signing key (64 hex chars = 32 bytes) for cookie persistence across restarts.
# Start keycloack
curl -o docker-compose.yaml https://raw.githubusercontent.com/tetratelabs/built-on-envoy/refs/heads/main/extensions/composer/saml/demo/keycloak/docker-compose-remote.yaml
docker compose -f docker-compose.yaml up --wait
# Download the IdP metadata
curl http://localhost:8080/realms/saml-demo/protocol/saml/descriptor -o idp-metadata.xml
# Run the plugin
boe run --extension saml --config '
{
"entity_id": "http://localhost:10000",
"acs_path": "/saml/acs",
"idp_metadata_xml": {"file": "idp-metadata.xml"},
"session": {
"cookie_name": "my_session",
"duration": "5m",
"cookie_domain": ".example.com",
"cookie_secure": true,
"cookie_signing_key": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
}
}'
# Test the plugin in the browser and login as testuser/testpass
# Check the cookie with browser dev tools to see how the settings applied
open http://localhost:10000
# Cleanup keycloak
docker compose -f docker-compose.yaml down -v Attribute Mapping and Bypass Paths
Map SAML attributes to upstream headers and bypass health check paths from authentication.
# Start keycloack
curl -o docker-compose.yaml https://raw.githubusercontent.com/tetratelabs/built-on-envoy/refs/heads/main/extensions/composer/saml/demo/keycloak/docker-compose-remote.yaml
docker compose -f docker-compose.yaml up --wait
# Download the IdP metadata
curl http://localhost:8080/realms/saml-demo/protocol/saml/descriptor -o idp-metadata.xml
# Run the plugin
boe run --extension saml --config '
{
"entity_id": "http://localhost:10000",
"acs_path": "/saml/acs",
"idp_metadata_xml": {"file": "idp-metadata.xml"},
"attribute_headers": {
"email": "x-saml-email",
"Role": "x-saml-role"
},
"bypass_paths": ["/health", "/ready", "/status/409"],
}'
# Test the plugin in the browser and login as testuser/testpass and check how the headers are set
open http://localhost:10000/headers
# Clear the session cookies and then open again the browser and check how authentication is bypassed
open http://localhost:10000/status/409
# Cleanup keycloak
docker compose -f docker-compose.yaml down -v