Searching HAProxy Enterprise 1.9r1
HAProxy Enterprise SAML Component Version 1.2
HAProxy Enterprise SAML Component Version 1.2
Before you begin
About SAML 2.0
The XML-based Security Assertion Markup Language (SAML) 2.0 open-standard transfers identity data (assertions) between an Identity Provider and a Service Provider.
- Identity Provider
-
Performs authentication on the Service Provider's behalf.
- Service Provider
-
Authorizes users to access the requested resource once they are authenticated by a trusted Identity Provider.
About HAProxy Enterprise SAML Component
HAProxy Enterprise SAML Component acts as a SAML Service Provider. It provides SP-initiated cross-domain web single-sign-on (SSO) to any web application located behind an HAProxy Enterprise server. You thus don't have to implement SAML directly in your application.
In an SP-initiated SSO flow, the Service Provider creates an Authentication Request (AuthnRequest) and redirects the user to the Identity Provider.
HAProxy Enterprise SAML Component checks user credentials against an Identity Provider such as Azure Active Directory, either on-premises or in the cloud.

HAProxy Enterprise SAML Component then grants or denies access to web applications based on SAML assertions sent by the Identity Provider.
Features
Implement SSO seamlessly, even for legacy web applications
Configure logging and grant access thanks to the HAProxy Enterprise ACL syntax
Check SAML assertions or attributes with XPath
-
Retrieve SAML assertions and use them as HAProxy Enterprise variables. For example, you can then:
Grant access to a group of users
Enhance logs
Pass user information to the application via HTTP headers
Architecture
HAProxy Enterprise SAML Component expands the functionalities of HAProxy Enterprise thanks to the Stream Processing Offload Engine.
HAProxy Enterprise SAML Component is a Stream Processing Offload Agent. It communicates with HAProxy Enterprise using the Stream Processing Offload Protocol.
Concepts and workflows
Single sign-on using SAML in a Web browser
The SSO workflow using a Web browser is as follows:

User does not have an authentication session at the Identity Provider
A user visits a web application (a SAML Service Provider).
The web application redirects the user's browser to the SAML Identity Provider via HAProxy Enterprise SAML Component.
HAProxy Enterprise SAML Component and the web application establish a trust relationship by exchanging certificates over HTTPS.
The user signs on, and the Identity Provider validates credentials.
HAProxy Enterprise SAML Component redirects the user's browser back to the web application with a SAML response containing a SAML authentication assertion. The response is sent to the web application's Assertion Consumer Service URL.
Authentication
When a user wants to access a web application:
HAProxy Enterprise SAML Component checks that the user has sent a valid SAML cookie.
-
- The user has sent a valid SAML cookie
-
HAProxy Enterprise SAML Component grants access to the web application.
- The user has not sent a valid SAML cookie
-
-
The user sends, through their browsers, a SAML AuthnRequest (Authentication Request) to the Identity Provider.
The AuthnRequest format is specific to the Identity Provider.
The Identity Provider asks the user to authenticate via an authentication portal or any other way (e.g., tokens or 2-factor authentication).
-
Once the user has successfully authenticated, the Identity Provider sends a SAML Response to the Service Provider via the user's browser.
The SAML Response is sent in a POST HTTP request.
It contains authorization and authentication information about the user, such as the user name, the user's email address, or any custom XML attribute, depending on the Service Provider configuration.
HAProxy Enterprise SAML Component analyzes this SAML Response and allows administrators to make specific checks or actions on XML attributes present in the SAML Response, and to take decisions based on the results.
-
Using web applications
As long as their browsers send a valid, non-expired, SAML cookie (called saml_cookie
), users are granted access to web applications.
Every action requested in the on_saml_response
category is executed on each subsequent HTTP response unless set_var_once
is specified.
Single Logout
When a user wants to log out:
-
HAProxy Enterprise SAML Component asks the Identity Provider to log out from any application where the user has previously logged in, by sending a LogoutRequest.
You can customize the Logout Request sent to the Identity Provider via the
logout_request_template_filename
configuration directive. The Identity Provider replies to every application and asks them to log the user out, using a Logout Response.
Prerequisites
To use HAProxy Enterprise SAML Component, you must have access to a SAML Identity Provider such as Azure Active Directory, Okta, Ping, or Microsoft ADFS, on-premises or in the cloud.
Installing HAProxy Enterprise SAML Component
Install HAProxy Enterprise SAML Component via your package manager.
To install the HAProxy Enterprise SAML Component on Ubuntu 20.04, run:
$ sudo apt install hapee-extras-spoa-saml
See also
HAProxy Enterprise SAML Component Azure Quick Start Guide
This Quick Start Guide will guide you through setting up a sandbox HAProxy Enterprise SAML Component implementation in a Ubuntu 20.04 LTS virtual machine
Warning
This setup is meant for test purposes only. Do not use it in a production environment.
We will enable single sign-on to a local NGINX instance. We will use Azure Active Directory as the Identity Provider. HAProxy Enterprise SAML Component will be the Service Provider.
In this quick start guide, you will:
Configure an Azure application
Configure an Ubuntu virtual machine
Start HAProxy Enterprise and HAProxy Enterprise SAML Component
Install HAProxy Enterprise and HAProxy Enterprise SAML Component on the virtual machine
Connect to your sample local application by providing Azure credentials
Conventions
The procedures below use the following icons:
-
Perform the step in Microsoft Azure.
-
Perform the procedure in the Ubuntu VM.
Configuring an Azure application
-
Define your sample local application's FQDN.
app.example.local
Creating an Azure Active Directory enterprise application
Perform the steps below on the Azure portal.
Launch a web browser, then sign in to the Microsoft Azure portal as a cloud application administrator, or as an application administrator for your Azure Active Directory tenant.
In Microsoft Azure, create a new non-gallery enterprise application in Azure Active Directory.
Click Assign users and groups, and grant access to the Azure Active Directory enterprise application to one or several users.
See also
Add an unlisted (non-gallery) application to your Azure AD organization
Exporting the tenant ID and usernames
Perform the steps below on the Azure portal.
Navigate to Azure Active Directory, then write down your tenant ID.
-
Write down the first name of one or several users who have access to your Azure Active Directory enterprise application from their user profiles.
We will whitelist users later on.
Setting up the basic SAML configuration
Perform the steps below on the Azure portal.
-
Select Sign-on, then click SAML.
The Set up Single Sign-On with SAML page appears.
-
Edit the Basic SAML Configuration:
- Identifier (Entity ID)
-
Enter a SAML ID for your application. For the sake of simplicity, enter your Azure Active Directory enterprise application's name.
This ID can only contain alphanumeric characters and underscores (
_
).
samlappaugust11
- Reply URL (Assertion Consumer Service URL)
-
Enter
https://<Your sample local application's FQDN>/saml/reply
. - Logout Url
-
Enter
https://<Your sample local application's FQDN>/saml/logout
.
Configuring the Ubuntu VM
-
Launch a new Ubuntu Desktop 20.04 LTS virtual machine.
Select the Bridged Network mode.
-
Connect to your VM via SSH or PuTTY.
Creating a sample local application
Perform the steps below on the Ubuntu VM.
We will set up an NGINX instance on the virtual machine as a sample application. It will listen on localhost on port 3200 and will not be SAML-enabled on its own.
Warning
In a production environment, your application would be hosted on a cluster of dedicated servers, on a private network.
Though the security level provided by this implementation is very poor, it is enough to show the basics of setting up HAProxy Enterprise SAML Component.
-
Install NGINX:
ubuntu@vm:~$ sudo apt install nginx -y
-
Customize the NGINX welcome page:
ubuntu@vm:~$ sudo sed -i 's/Welcome to nginx/My SAML application/' \ /var/www/html/index.nginx-debian.html
-
Make the NGINX instance listen on port 3200:
ubuntu@vm:~$ sudo sed -i 's/80/3200/' /etc/nginx/sites-enabled/default
ubuntu@vm:~$ sudo systemctl restart nginx
Creating variables
Perform the steps below on the Ubuntu VM.
-
Add the following variables to a new
variables.txt
file:export myazureapp=<Your Azure application's name> export idp_app_id=<Your Azure application ID> export idp_tenant_id=<Your Azure Active Directory tenant ID> export myappfqdn=<Your sample local application's FQDN> export myappsocketpadress=<Your sample local application's IP:port> export samlapp=<Internal name for your sample local application> export samlappusers=<Space delimited list of users' first names> export lbipaddress=<HAProxy Enterprise's IP address> export hapeeversion=<HAProxy Enterprise Major Version Number> export hapeekey=<HAProxy Enterprise Key>
ubuntu@vm:~$ cat <<EOF > variables.txt export myazureapp=samlappaugust11 export idp_app_id=0000b000-00a0-0000-00c0-0000c000a0c0 export idp_tenant_id=0fbb0000-0000-00ad-b00e-f00000000000 export myappfqdn=app.example.local export myappsocketpadress=192.168.1.10:3200 export samlapp="\$myazureapp" export samlappusers='Elena John Mary\\ Lou' export lbipaddress=127.0.0.1 export hapeeversion=1.9 export hapeekey=xxxxxxxx-xxxxxxxx EOF
Installing required packages
Perform the steps below on the Ubuntu VM.
-
Install cURL, HAProxy Enterprise, and HAProxy Enterprise SAML Component:
ubuntu@vm:~$ source variables.txt
ubuntu@vm:~$ sudo apt install curl -y
ubuntu@vm:~$ curl -s https://cdn.haproxy.com/static/install_haproxy_enterprise.sh | sudo bash /dev/stdin 1.9r1 $hapeekey
ubuntu@vm:~$ sudo apt install hapee-extras-spoa-saml -y
Creating a self-signed SSL certificate
Perform the steps below on the Ubuntu VM.
-
Create a self-signed SSL certificate to allow connecting via HTTPS:
ubuntu@vm:~$ source variables.txt
ubuntu@vm:~$ openssl req -keyout key.pem \ -out cert.pem -x509 -sha256 -nodes -days 365 -newkey rsa:2048 \ -subj "/C=FR/ST=IdF/L=Paris/O=HAProxy Technologies/OU=IT/CN=$myappfqdn"
Your sample local application's FQDN is used in the certificate Common Name. The certificate is valid only if the request hostname matches the common name.
-
Concatenate the key and the certificate into a new certificate:
ubuntu@vm:~$ cat key.pem cert.pem | sudo tee /etc/hapee-$hapeeversion/certs/$samlapp.pem
Creating the HAProxy Enterprise configuration file
Perform the steps below on the Ubuntu VM.
The HAProxy Enterprise hapee-lb.cfg
configuration file will contain:
A SAML frontend to redirect user requests to HAProxy Enterprise SAML Component
-
The three following backends:
A backend for the Stream Processing Offload Engine
A default backend to manage errors
A backend for your sample local application
-
Create the HAProxy Enterprise
hapee-lb.cfg
configuration file:The
bind :443 ssl
directive performs SSL termination on HAProxy Enterprise. You can then leverage HAProxy Enterprise to implement SSL in all your applications, whatever the underlying technologies.ubuntu@vm:~$ source variables.txt
ubuntu@vm:~$ cat <<EOF | sudo tee /etc/hapee-2.1/hapee-lb.cfg frontend ft-saml bind :80 bind :443 ssl crt /etc/hapee-$hapeeversion/certs/$samlapp.pem mode http option http-buffer-request tcp-request inspect-delay 10s timeout client 1m http-request set-var(sess.saml_app) str($samlapp) if { hdr(host) -i $myappfqdn } filter spoe engine spoe-saml config /etc/hapee-extras/hapee-saml-spoe.cfg http-request send-spoe-group spoe-saml spoe-group-req http-request redirect location %[var(txn.saml.redirect_to)] code 302 if { var(txn.saml.redirect_to) -m found } http-request deny if ! { var(txn.saml.saml_auth_ok) -m bool } ! { var(txn.saml.saml_logout_ok) -m bool } http-request set-header givenname %[var(txn.saml.givenname)] http-request set-header display_name %[var(txn.saml.display_name)] http-request set-header all_attributes_names %[var(txn.saml.all_attributes_names)] http-request set-header all_attributes_values %[var(txn.saml.all_attributes_values)] http-request set-header AuthnInstant %[var(txn.saml.AuthnInstant)] http-request set-header AuthnInstant_ts %[var(txn.saml.AuthnInstant_ts)] http-response set-header Set-Cookie %[var(txn.saml.set_cookie)] if { var(txn.saml.set_cookie) -m found } http-response set-header saml-auth-error-text %[var(txn.saml.saml_auth_error_text)] if { var(txn.saml.saml_auth_error_text) -m found } http-response set-header location %[var(txn.saml.redirect_after_auth)] if { var(txn.saml.redirect_after_auth) -m found } http-response set-status 303 if { var(txn.saml.redirect_after_auth) -m found } default_backend bk-err use_backend %[var(txn.saml.saml_app_backend)] if { var(txn.saml.saml_app_backend) -m found } backend bk-spoe mode tcp timeout connect 5s timeout server 30s server auth-server-spoe 127.0.0.1:12345 backend bk-err mode http backend bk-$samlapp option forwardfor mode http server $samlapp $myappsocketpadress timeout connect 30s timeout server 1m EOF
Creating the HAProxy Enterprise SAML Component initialization file
Perform the steps below on the Ubuntu VM.
-
Create the HAProxy Enterprise SAML Component
saml.ini
initialization file:ubuntu@vm:~$ source variables.txt
ubuntu@vm:~$ cat <<EOF | sudo tee /etc/hapee-extras/saml.ini config_version = 1.0.0 [$samlapp] {{IDP_APP_NAME}} = $myazureapp {{IDP_APP_ID}} = $idp_app_id {{IDP_TENANT_ID}} = $idp_tenant_id {{CLAIM_PREFIX}} = http://schemas.xmlsoap.org/ws/2005/05/identity/claims {{APP_FQDN}} = $myappfqdn {{APP_LOGIN_URL}} = https://{{APP_FQDN}}/saml/reply {{APP_LOGOUT_URL}} = https://{{APP_FQDN}}/saml/logout {{APP_BACKEND}} = bk-{{APP_NAME}} saml_cookie_secure = 0 saml_cookie_samesite = Lax saml_cookie_httponly = 0 saml_cookie_lifetime = 3600 saml_cookie_time_offset = 0 saml_cookie_domain = {{APP_FQDN}} authn_request_template_filename = authn_request.xml logout_request_template_filename = logout_request.xml saml_app_backend = {{APP_BACKEND}} sign_authn_requests=0 sign_logout_requests=0 verify_signature=0 app_login_url = {{APP_LOGIN_URL}} app_logout_url = {{APP_LOGOUT_URL}} idp_login_url = https://login.microsoftonline.com/{{IDP_TENANT_ID}}/saml2 idp_logout_url = https://login.microsoftonline.com/logout.srf ; this field is also used to detect redirect loops between the IDp and our app idp_referer_url = https://login.microsoftonline.com/ on_saml_response check_schema on_saml_response check_attr entity_id spn:{{IDP_APP_ID}} on_saml_response check_attr version on_saml_response check_attr status_code on_saml_response check_attr issuer https://sts.windows.net/{{IDP_TENANT_ID}}/ on_saml_response check_attr issue_instant on_saml_response check_attr destination {{APP_LOGIN_URL}} on_saml_response check_attr assertion required_count=1 on_saml_response check_conditions required_count=1 on_saml_response check_subject_confirmation_data required_count=1 ; Get all the SAML attributes names on_saml_response check_attr set_var=all_attributes_names set_var_sep=| xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute/@Name ; Get all the SAML attributes values on_saml_response check_attr set_var=all_attributes_values set_var_sep=| xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute/saml:AttributeValue/text() ; Get the User Display Name provided in SAML Responses or Logout Requests on_saml_response check_attr set_var=display_name xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name='http://schemas.microsoft.com/identity/claims/displayname']/@Name on_saml_response check_attr set_var=AuthnInstant_ts xpath=/samlp:Response/saml:Assertion/saml:AuthnStatement/@AuthnInstant set_var_as_timestamp on_saml_response check_attr set_var=AuthnInstant xpath=/samlp:Response/saml:Assertion/saml:AuthnStatement/@AuthnInstant on_logout_request check_attr set_var=display_name xpath=/samlp:LogoutRequest/saml:NameID/text() on_logout_request check_attr destination {{APP_LOGOUT_URL}} required on_logout_request check_attr issuer https://sts.windows.net/{{IDP_TENANT_ID}}/ required EOF
Creating the Microsoft Azure templates
Perform the steps below on the Ubuntu VM.
-
Copy the Microsoft Azure example authentication request and logout request templates to the HAProxy Enterprise configuration directory:
ubuntu@vm:~$ sudo cp /etc/hapee-extras/saml_examples/azure/authn_request.xml \ /etc/hapee-extras/
ubuntu@vm:~$ sudo cp /etc/hapee-extras/saml_examples/azure/logout_request.xml \ /etc/hapee-extras/
Starting HAProxy Enterprise and HAProxy Enterprise SAML Component
Perform the steps below on the Ubuntu VM.
-
Start HAProxy Enterprise and HAProxy Enterprise SAML Component:
ubuntu@vm:~$ sudo systemctl enable hapee-extras-spoa-saml
Synchronizing state of hapee-extras-spoa-saml.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable hapee-extras-spoa-saml Created symlink /etc/systemd/system/multi-user.target.wants/hapee-extras-spoa-saml.service → /lib/systemd/system/hapee-extras-spoa-saml.service.
ubuntu@vm:~$ sudo systemctl start hapee-extras-spoa-saml
ubuntu@vm:~$ sudo systemctl enable hapee-1.9-lb
Synchronizing state of hapee-2.1-lb.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable hapee-2.1-lb Created symlink /etc/systemd/system/multi-user.target.wants/hapee-2.1-lb.service → /lib/systemd/system/hapee-2.1-lb.service.
ubuntu@vm:~$ sudo systemctl start hapee-1.9-lb
Connecting to your sample local application
Perform the steps below on the Ubuntu VM.
-
Redirect your NGNIX instance's Fully Qualified Domain Name to the IP address your HAProxy Enterprise instance is listening on in the
/etc/hosts
file:ubuntu@vm:~$ echo "127.0.0.1 $myappfqdn" | sudo tee -a /etc/hosts
-
Connect to your sample local application's Fully Qualified Domain Name via a web browser.
Connect to
http://app.example.local
.Note
Your NGINX instance listens on port 3200. You are then actually connecting to HAProxy Enterprise.
-
Sign on to the Microsoft Azure portal with your Microsoft Azure credentials.
You can safely ignore the warning message since we use a self-signed certificate.
The NGINX instance's welcome page displays.
Troubleshooting
Perform the steps below on the Ubuntu VM.
If an error occurs:
-
Stop HAProxy Enterprise SAML Component:
ubuntu@vm:~$ sudo service saml stop
# Stopping spoa-saml (pid 8831 according to /var/run/saml.pid) ... Waiting.. --> removing stale pid file ... ==> stop spoa-saml Done.
-
Start HAProxy Enterprise SAML Component in debug mode:
ubuntu@vm:~$ /opt/hapee-extras/bin/hapee-saml -C /etc/hapee-extras/ \ -f /etc/hapee-extras/saml.ini --debug-all -F >> /tmp/log_file 2>&1
Repeat the steps that led to the error, then analyze the
/tmp/log_file
file.
Whitelisting or blacklisting usernames
Perform the steps below on the Ubuntu VM.
You can whitelist or blacklist users at the Service Provider level, whatever the Identity Provider.
-
Insert the following directive in the HAProxy Enterprise SAML Component
saml.ini
initialization file:on_saml_response check_subject_confirmation_data/a on_saml_response check_attr optional set_var_cnt set_var=givenname xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"]/saml:AttributeValue/text()'
ubuntu@vm:~$ sudo sed -i '/on_saml_response check_subject_confirmation_data/a on_saml_response check_attr optional set_var_cnt set_var=givenname xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"]/saml:AttributeValue/text()' /etc/hapee-extras/saml.ini
-
Insert the following directive in the HAProxy Enterprise
hapee-lb.cfg
configuration file'sfrontend ft-saml
section:http-request deny if ! { var(txn.saml.<Internal name for your sample local application>.givenname) <Space delimited list of users' first names> }"
http-request deny if ! { var(txn.saml.MySAMLApp.givenname) Elena John Mary\ Lou }"
ubuntu@vm:~$ sudo sed -i "/http-request deny/a \ http-request deny if ! { var(txn.saml.$samlapp.givenname) $samlappusers }" /etc/hapee-2.1/hapee-lb.cfg
-
Restart HAProxy Enterprise and HAProxy Enterprise SAML Component:
ubuntu@vm:~$ sudo systemctl reload hapee-1.9-lb
ubuntu@vm:~$ sudo systemctl stop hapee-extras-spoa-saml
ubuntu@vm:~$ sudo /opt/hapee-extras/bin/hapee-saml -C /etc/hapee-extras/ -f /etc/hapee-extras/saml.ini
Sign on to your sample local application with a whitelisted username, then with another username.
Tip
To blacklist users, remove the !
sign before the condition.
Reference guide
HAProxy Enterprise configuration file sections
Frontend
frontend ft-saml bind :80 bind :443 ssl crt mycert.pem mode http option http-buffer-request tcp-request inspect-delay 10s timeout client 1m http-request set-var(sess.saml_app) str(MySAMLApp) if { hdr(host) -i app.example.local } filter spoe engine spoe-saml config /etc/hapee-extras/hapee-saml-spoe.cfg http-request send-spoe-group spoe-saml spoe-group-req http-request redirect location %[var(txn.saml.redirect_to)] code 302 if { var(txn.saml.redirect_to) -m found } http-request deny if ! { var(txn.saml.saml_auth_ok) -m bool } ! { var(txn.saml.saml_logout_ok) -m bool } http-request set-header givenname %[var(txn.saml.givenname)] http-request set-header displayname %[var(txn.saml.displayname)] http-request set-header all_attributes_names %[var(txn.saml.all_attributes_names)] http-request set-header all_attributes_values %[var(txn.saml.all_attributes_values)] http-request set-header AuthnInstant %[var(txn.saml.AuthnInstant)] http-request set-header AuthnInstant_ts %[var(txn.saml.AuthnInstant_ts)] http-response set-header Set-Cookie %[var(txn.saml.set_cookie)] if { var(txn.saml.set_cookie) -m found } http-response set-header saml-auth-error-text %[var(txn.saml.saml_auth_error_text)] if { var(txn.saml.saml_auth_error_text) -m found }
Key directives
-
Declare a SAML frontend to redirect user requests to HAProxy Enterprise SAML Component:
frontend ft-saml
-
Listen to incoming traffic over HTTP and HTTPS:
bind :80
-
Listen to incoming traffic over HTTPS and enable SSL termination:
bind :443 ssl crt mycert.pem
Note
The CRT parameter identifies the PEM-formatted SSL certificate location. This certificate should contain both the HAProxy Enterprise server's public certificate and private key.
-
Wait for the whole HTTP request body before forwarding it to HAProxy Enterprise SAML Component :
option http-buffer-request
-
Set the maximum time to wait for data during content inspection to 10 seconds:
tcp-request inspect-delay 10s
-
Set variable sess.saml_app to MySAMLApp if the HTTP request's host header field matches app.example.local, ignoring case:
Note
Replace app.example.local by the section header of your HAProxy Enterprise SAML Component
saml.ini
initialization file, and edit the ACL as needed. See SAML application backend.http-request set-var(sess.saml_app) str(MySAMLApp) if { hdr(host) -i app.example.local }
-
Declare the spoe-saml SPOE filter and its
hapee-saml-spoe.cfg
configuration file, to forward streaming data to HAProxy Enterprise SAML Component:filter spoe engine spoe-saml config /etc/hapee-extras/hapee-saml-spoe.cfg
-
Send messages to HAProxy Enterprise SAML Component; define the spoe-group-req group of messages to send via a
spoe-group
section in thehapee-saml-spoe.cfg
SPOE configuration file:http-request send-spoe-group spoe-saml spoe-group-req
-
Redirect the user to the value of variable txn.saml.redirect_to:
http-request redirect location %[var(txn.saml.redirect_to)] code 302 if { var(txn.saml.redirect_to) -m found }
See also
Configuring HAProxy Enterprise for Transport Layer Security (TLS)
Backends
Add the following backend sections:
Stream Processing Offload Engine backend:
backend bk-spoe mode tcp timeout connect 5s timeout server 30s server auth-server-spoe 127.0.0.1:12345
Change the socket address on the server line to match your setup.
You can use the spoa-saml
-A and -P options to change the IP address and the port.
Default backend to manage errors
backend bk-err mode http
Make it the default backend in the frontend section:
default_backend bk-err
If no target backend has been set, the fallback backend is bk-err. The user is not granted access and receives a 502 error.
SAML application backend
backend bk-MySAMLApp option forwardfor mode http server app1 127.0.0.1:3200 timeout connect 30s timeout server 1m
Warning
Before sending the HAProxy Enterprise requests to the Stream Processing Offload Agent, you must set the sess.saml_app
variable to the name of the application.
This application must have a dedicated section in the HAProxy Enterprise SAML Component saml.ini
initialization file.
See also
HAProxy Enterprise SAML Component saml.ini
initialization file
You can configure several applications in the HAProxy Enterprise SAML Component saml.ini
initialization file, one per section.
To configure an application called MySAMLApp
, use [MySAMLApp] as the section header.
Configuration options
config_version
Version of the configuration file. For upward compatibility.
- Type
-
string
idp_login_url
URL of the Identity Provider's web authentication portal.
- Type
-
string
- Example
-
On Microsoft Azure, https://login.microsoftonline.com/{{IDP_APP_ID}}/saml2.
idp_logout_url
Single Logout URL. Endpoint which will initiate the SAML Logout for all applications.
- Type
-
string
- Example
-
On Microsoft Azure, https://login.microsoftonline.com/logout.srf
idp_referer_url
HTTP Referer value to check when receiving HTTP data from the Identity Provider.
- Type
-
string
- Example
-
On Microsoft Azure, https://login.microsoftonline.com/.
app_login_url
URL where the application expects to receive the SAML Response from the Identity Provider. The reply URL is also referred to as the Assertion Consumer Service.
- Type
-
string
app_logout_url
When the users browse this URL, a LogoutRequest is sent to the Identity Provider.
- Type
-
string
signing_algo
Cryptographic algorithm used to sign sent requests.
- Type
-
string
idp_public_cert
Identity Provider's X509 public certificate of the (in base64 .pem format). Used to verify SAML Responses' "Response" and "Assertion" attributes.
- Type
-
string
verify_signature
Verify the signature of incoming SAML requests.
- Type
-
boolean
- Default value
-
0
require_signed_response
Fail if the XML response is not signed.
- Type
-
boolean
- Default value
-
0
require_signed_assertion
Fail if the XML assertion is not signed.
- Type
-
boolean
- Default value
-
0
signing_key
Private key used to sign sent requests.
- Type
-
string
sign_authn_requests
Set to 1 to sign Authn Requests.
- Type
-
boolean
- Default value
-
0
sign_logout_requests
Set to 1 to sign Logout Requests.
- Type
-
boolean
- Default value
-
0
saml_app_backend
Backend name for this application.
- Type
-
string
- Default value
-
bk-{{APP_NAME}}
saml_cookie_secure
Use the cookie only for HTTPS, not for HTTP (this can lead to an infinite loop between your application and the Identity Provider).
- Type
-
boolean
- Default value
-
0
saml_cookie_samesite
See https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Set-Cookie/SameSite
- Type
-
string
saml_cookie_httponly
- Type
-
boolean
- Default value
-
1
saml_cookie_time_offset
- Type
-
integer
- Default value
-
0
saml_cookie_lifetime
- Type
-
integer
- Default value
-
36000
Actions
on_saml_response check_attr
Check any attribute in a SAML Response. You can use XPath=<xpath_expression> set_var=<my_var_name> to set it in an HAProxy variable.
By default, the SAML Response validation fails if you do not specify an attribute. Use the 'optional' flag to make the SAML Response validation succeed even if no attribute is specified.
on_saml_response check_schema
Validate the SAML response against the SAML 2.0 XSD schema.
on_saml_response check_conditions
Check the <SubjectConfirmationData> XML attribute, including NotBefore and NotOnOrAfter values.
on_saml_response check_subject_confirmation_data
Check the <Condition> XML attribute, including NotBefore and NotOnOrAfter values.
on_saml_response check_attr entity_id
Check that the audience <AudienceRestriction><Audience> attribute exists.
- Optional
-
Specific entity_id value to check.
on_saml_response check_attr version
Check that the SAML protocol version is 2.0.
on_saml_response check_attr status_code
Check the SAMLResponse status code.
- Optional
-
Status to match. Otherwise compare to "urn:oasis:names:tc:SAML:2.0:status:Success".
on_saml_response check_attr destination
Check that the SAMLResponse Destination value matches this item.
- Mandatory
-
Destination to match. You can use '<APP_LOGIN_URL>' to match the configured app_login_url. On Microsoft Azure, it must match the URL Assertion Consumer Service (ACS).
on_saml_response check_attr issuer
Check the Issuer attribute of the SAMLResponse.
- Optional
-
Specific value to check.
on_saml_response check_attr issue_instant
Check that the IssueInstant attribute exists. It can be set in a variable by using 'set_var' and set in the for of a timestamp, using 'set_var_as_timestamp'.
on_saml_response check_attr assertion
Check that the Assertion attribute exists.
on_logout_request check_attr
Check any attribute in a Logout Request. You can use XPath=<xpath_expression> set_var=<my_var_name> to set it in an HAProxy variable.
on_logout_request check_attr issuer
Check the issuer attribute of the LogoutRequest.
- Optional
-
Specific value to check.
on_logout_request check_attr name_id
Check that the nameId attribute exists in LogoutRequest.
on_logout_request check_attr destination
Check that the LogoutRequest destination value matches this item.
- Mandatory
-
Destination to match.
Note
You can use {{APP_LOGOUT_URL}} to match the configured app_logout_url.
Microsoft Azure HAProxy Enterprise SAML Component saml.ini
initialization file example
This example is intended to be used with Microsoft Azure. To use HAProxy Enterprise SAML Component with other Identity Providers, this configuration file needs some adjustments.
Variables
- {{ID_APP_NAME}}
-
Name of your application in Azure Active Directory.
- {{IDP_APP_ID}}
-
Application ID provided by the Identity Provider (Azure Active Directory).
For instance: aa0aaaaa-0aa0-000a-a0a0-aa0000a0000a.
- {{IDP_TENANT_ID}}
-
aaa000a0-0000-0a00-0000-000a00a00a0
- {{CLAIM_PREFIX}}
- {{APP_FQDN}}
-
Fully Qualified Domain Name of the Identity Provider (Azure Active Directory).
dkorunichaproxy.onmicrosoft.com
- {{APP_LOGIN_URL}}
-
Assertion Consumer Service URL, depending on your application. Value of
app_login_url
for this application.{{APP_LOGIN_URL}} is automatically replaced if you specify it in the HAProxy Enterprise SAML Component
saml.ini
initialization file. - {{APP_LOGOUT_URL}}
-
Value of
app_logout_url
for this application.Logout URL, depending on your application.
https://{{APP_FQDN}}/saml/logout
- {{APP_BACKEND}}
-
Backend on which the application is available.
bk-{{APP_NAME}}: {{APP_NAME}} will be replaced with the section name.
If the section header is [MySAMLApp], the backend is called bk-MySAMLApp.
saml.ini
example
config_version = 1.0.0 [MySAMLApp] = xxx # the name of your application in Azure AD = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx = http://schemas.xmlsoap.org/ws/2005/05/identity/claims = xxx # ex: app1.example.local = https:///saml/reply # ACS url, depending on your application = https:///saml/logout # logout url, depending on your application = bk- # APP_NAME will be replaced with the section name saml_cookie_secure = 0 saml_cookie_httponly = 1 saml_cookie_lifetime = 3600 saml_cookie_time_offset = 0 saml_cookie_domain = authn_request_template_filename = authn_request.xml logout_request_template_filename = logout_request.xml saml_app_backend = idp_login_url = https://login.microsoftonline.com//saml2 idp_logout_url = https://login.microsoftonline.com//saml2 app_login_url = app_logout_url = idp_referer_url = https://login.microsoftonline.com/ on_saml_response check_schema verify_signature=0 on_saml_response check_attr entity_id spn: on_saml_response check_attr version on_saml_response check_attr status_code on_saml_response check_attr issuer https://sts.windows.net/ on_saml_response check_attr issue_instant on_saml_response check_attr destination on_saml_response check_attr assertion required_count=1 on_saml_response check_conditions required_count=1 on_saml_response check_subject_confirmation_data required_count=1 on_logout_request check_attr destination required on_logout_request check_attr issuer https://sts.windows.net// required on_saml_response check_attr optional set_var_cnt set_var=givenname xpath=/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name="/givenname"]/saml:AttributeValue/text()
Note
You can use retrieved XML attributes in HTTP rules in the HAProxy Enterprise hapee-lb.cfg
configuration file:
-
To restrict acess:
For instance:
http-request deny if ! \{ var(txn.givenname) user1 user2 user3 }
-
To set HTTP headers:
For instance:
set-header myname %[var(txn.givenname)]
AuthnRequest template
Here is an example of an Authentication Request template. You can send generated AuthnRequests to Microsoft Azure:
- authn_request.xml
-
<samlp:AuthnRequest xmlns="urn:oasis:names:tc:SAML:2.0:metadata" ID="id%%RANDOM_ID_HEX_32%%" Version="2.0" IssueInstant="%%NOW_WITH_MS%%" ForceAuthn="false" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">{{IDP_APP_ID}}</Issuer> </samlp:AuthnRequest>
You can specify templates via the authn_request_template_filename
configuration directive. The path is relative to the configuration directory. You can specify a custom directory via the -C
command-line option.
The following patterns are automatically replaced:
- %%NOW%%
-
Current time in ISO 8601 format.
2020-01-28T15:25:14Z
- %%NOW_WITH_MS%%
-
Current time in ISO 8601 format, including milliseconds.
2020-01-28T15:25:14.884Z
- %%RANDOM_ID_HEX_32%%
-
32-char random ID, comprising the following characters: 0123456789abcdef.
- %%ISSUER%%
-
Replace manually by the value expected by your Identity Provider. On Microsoft Azure, you can replace it with:
-
- Your Microsoft Azure Application ID
-
The
entity_id
received in the SAML Response is spn:<Application ID>.ae7edebf-2db4-476f-b1a9-bf5782b1799a5b25e637
-
- The name of your application in Microsoft Azure
-
The
entity_id
received in the SAML Response is this very issuer.
If your application name in this configuration file is the same as the one in Microsoft Azure, you can use {{APP_NAME}}.
-
- ForceAuthn="false"
-
If set to True, users have to reauthenticate, even if they already have a valid session.
LogoutRequest template
You can use a similar template for Logout Requests:
- logout_request.xml
-
<samlp:LogoutRequest xmlns="urn:oasis:names:tc:SAML:2.0:metadata" ID="id%%RANDOM_ID_HEX_32%%" Version="2.0" IssueInstant="%%NOW_WITH_MS%%" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">{{IDP_APP_ID}}</Issuer> <NameID xmlns="urn:oasis:names:tc:SAML:2.0:assertion">%%NAME_ID%%</NameID> </samlp:LogoutRequest>
The following patterns are automatically replaced:
- %%ISSUER%%
-
Value from the SAML Response.
In Microsoft Azure, the following template applies:
https://sts.windows.net/<MS application ID>/
- %%NameID%%
-
Value from the SAML Response, usually the user's email address.
Actions
on_saml_response check_attr
Check any attribute in a SAML Response. You can use XPath=<xpath_expression> set_var=<my_var_name> to set it in an HAProxy variable.
By default, the SAML Response validation fails if you do not specify an attribute. Use the 'optional' flag to make the SAML Response validation succeed even if no attribute is specified.
on_saml_response check_schema
Validate the SAML response against the SAML 2.0 XSD schema.
on_saml_response check_conditions
Check the <SubjectConfirmationData> XML attribute, including NotBefore and NotOnOrAfter values.
on_saml_response check_subject_confirmation_data
Check the <Condition> XML attribute, including NotBefore and NotOnOrAfter values.
on_saml_response check_attr entity_id
Check that the audience <AudienceRestriction><Audience> attribute exists.
- Optional
-
Specific entity_id value to check.
on_saml_response check_attr version
Check that the SAML protocol version is 2.0.
on_saml_response check_attr status_code
Check the SAMLResponse status code.
- Optional
-
Status to match. Otherwise compare to "urn:oasis:names:tc:SAML:2.0:status:Success".
on_saml_response check_attr destination
Check that the SAMLResponse Destination value matches this item.
- Mandatory
-
Destination to match. You can use '<APP_LOGIN_URL>' to match the configured app_login_url. On Microsoft Azure, it must match the URL Assertion Consumer Service (ACS).
on_saml_response check_attr issuer
Check the Issuer attribute of the SAMLResponse.
- Optional
-
Specific value to check.
on_saml_response check_attr issue_instant
Check that the IssueInstant attribute exists. It can be set in a variable by using 'set_var' and set in the for of a timestamp, using 'set_var_as_timestamp'.
on_saml_response check_attr assertion
Check that the Assertion attribute exists.
on_logout_request check_attr
Check any attribute in a Logout Request. You can use XPath=<xpath_expression> set_var=<my_var_name> to set it in an HAProxy variable.
on_logout_request check_attr issuer
Check the issuer attribute of the LogoutRequest.
- Optional
-
Specific value to check.
on_logout_request check_attr name_id
Check that the nameId attribute exists in LogoutRequest.
on_logout_request check_attr destination
Check that the LogoutRequest destination value matches this item.
- Mandatory
-
Destination to match.
Note
You can use {{APP_LOGOUT_URL}} to match the configured app_logout_url.
Action flags
optional
This argument is not required.
required
This argument is mandatory.
nofail
For testing purposes. This action never fails, even if it returns an error.
required_count=<count>
Fails if the number of searched elements is different from <count>.
xpath=<XPath expression>
XPath expression to look for. Use with check_attr
actions.
expected=<expected_value>
Fails if the XPath result is different from this expression.
set_var=<var_name>
If one or more XPath results are found, store their values in this variable. The variable name is then prefixed with the application name followed by a dot.
If you set set_var=myvar
, the value is available in the HAProxy Enterprise hapee-lb.cfg
configuration file via %[var(txn.saml.MySAMLApp.myvar)]
.
set_var_once
The variable is set only after the POST request from the SAML Identity Provider. Otherwise, it is set each time the SAML cookie is found.
set_var_cnt
The number of XPath results is stored into variable <APP_NAME>.<VAR_NAME>_cnt
.
set_var_as_timestamp
If used with a value in ISO 8601 date and time format, the variable is converted to a timestamp.
2020-01-28T15:25:14.884Z
set_var_sep=<separator>
If multiple results are returned from the XPath query, separate them with this character.
set_var_default=<default_value>
Default value used if the XPath expression does not match.
sign_auth_requests
Set to 1 to sign authentication requests.
sign_logout_requests
Set to 1 to sign logout requests.
signing_algo
Cryptographic algorithm used to sign outbound requests.
signing_key
Private key used to sign outbound requests.
verify_signature
Verify the signature of incoming SAML requests.
Running HAProxy Enterprise SAML Component
To run HAProxy Enterprise SAML Component, run the following command:
~$ /opt/hapee-extras/bin/hapee-saml -C <config_dir> -f <SAML configuration file>
~$ /opt/hapee-extras/bin/hapee-saml -C spoa-saml/examples -f /etc/hapee-extras/saml.ini
- Usage
-
hapee-saml [OPTION]...
- -h
-
Print this message.
- -f config_file
-
.ini
file containing the SAML configuration. - -C config_dir
-
Directory containing the configuration file and the SAML templates.
- -l --licenses
-
Print software licenses.
- -v --version
-
Print product version.
- --debug-spoe -d
-
Debug Stream Processing Offload Engine.
- --debug-spoe-variables
-
Debug Stream Processing Offload Engine variables.
- --debug-saml
-
Debug SAML actions.
- --debug-xml
-
Debug XML parsing.
- --debug-config
-
Debug configuration parsing.
- --debug-all
-
Debug all, except the configuration parsing.
- --print-cfg
-
Display configuration during startup.
- --check-cfg -c
-
Check configuration, then exit.
- --gid
-
Run in the specified group.
- --uid
-
Run as the specified user.
- -F
-
Disable syslog output, and run in the foreground.
- -s
-
Use syslog.
- -p <pidfile>
-
Write the server PID to the specified file.
- -A <address>
-
Listen on this address.
- -P <port>
-
Specify the port to listen on.
Default value: 12345
- -n <num-workers>
-
Specify the number of workers.
- -b <conn-backlog>
-
Specify the connection backlog value.
Default value: 10
Troubleshooting
Debug mode
If requests are denied or authentication fails, you can start the program with --debug-all -F
to get more verbose output.
~$ hapee-saml -f /etc/hapee-extras/saml.ini --debug-all -F
1586529662.886993 [00] Config version supported: 1.0.0
1586529662.887347 [00] Config version 1.0.0
1586529662.889158 [00] add namespace 0: samlp->urn:oasis:names:tc:SAML:2.0:protocol
1586529662.889413 [00] add namespace 1: saml->urn:oasis:names:tc:SAML:2.0:assertion
[...]
Testing XPath expressions
Run HAProxy Enterprise SAML Component in debug mode.
Save the SAML Response to a text file.
-
Use the
xmllint
command-line XML tool to test XPath expressions.The
xmllint
command is provided in thelibxml2
package.
$ hapee-saml -f /etc/hapee-extras/saml.ini --debug-all -F >> log_file 2>&1
$ xmllint --shell SAMLResponse.xml
setns saml=urn:oasis:names:tc:SAML:2.0:assertion
setns samlp=urn:oasis:names:tc:SAML:2.0:protocol
xpath /samlp:Response/@Destination
Various online XPath test tools are available online. Be careful not to send confidential information.
Infinite loop
If an infinite loop between your application and the Identity Provider occurs when trying to access a resource, check your cookie_secure setting. If set to 1, your browser will only use the cookie for HTTPS, not for plain HTTP.
Also check your saml_cookie_domain and make sure it matches the domain of your application. Too strict security settings of your browsers can also prevent, in some situations, the cookie to be sent to your application. Also, you might need to set the saml_cookie_samesite value to None (which requires setting saml_cookie_secure to 1 on modern browsers).
Before you go into production
Set saml_cookie_secure to 1.
Enable XML signatures if supported by your Identity Provider and your setup.
Depending on how your Identity Provider handles logouts, ensure that the LogoutRequest is sent to your application along with a cookie.
-
Some Identity Providers' cookies (for example, Azure's) are regarded as third-party (these Identity Providers use an iframe to send the LogoutRequest to your application).
These cookies might be blocked by your browser, depending on its configuration and the value of the SameSite cookie attribute.
Set the SameSite to 0 or 1 via the saml_cookie_samesite configuration item.
-
To test logout, check that the LogoutRequest returns a 200 code and is received by your application.
Successful LogoutRequests also set the txn.saml.saml_logout_ok HAProxy Enterprise variable to 1.