Single sign-on

Single sign-on (SAML)

HAProxy Enterprise Security Assertion Markup Language (SAML) Component acts as a SAML Service Provider, providing single-sign-on (SSO) to any web application located behind an HAProxy Enterprise server.

This section provides an overview of HAProxy Enterprise SAML module.

About SAML 2.0 Jump to heading

The XML-based Security Assertion Markup Language (SAML) 2.0 open-standard transfers identity data (assertions) between an Identity Provider (IdP) and a Service Provider (SP).

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 the HAProxy Enterprise SAML module Jump to heading

HAProxy Enterprise SAML module acts as a SAML Service Provider. It provides Service Provider-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 Service Provider-initiated SSO flow, the Service Provider creates an Authentication Request (AuthnRequest) and redirects the user to the Identity Provider.

HAProxy Enterprise SAML module checks user credentials against an Identity Provider such as Microsoft Entra, either on-premises or in the cloud.

SAML overview

HAProxy Enterprise SAML module 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 using HAProxy Enterprise ACL capabilities
  • Check SAML assertions or attributes with XPath (via the saml.ini file)
  • Retrieve SAML assertions and use them as HAProxy Enterprise variables. For example, you can then enhance logs and pass user information to the application via HTTP headers

HAProxy Enterprise SAML module uses the Stream Processing Offload Engine to expand the functionalities of HAProxy Enterprise. It communicates with HAProxy Enterprise using the Stream Processing Offload Protocol.

Workflow:

  1. A user visits a web application that has HAProxy Enterprise in front of it.

  2. HAProxy Enterprise redirects the user’s browser to the SAML Identity Provider via HAProxy Enterprise SAML module.

  3. The user signs on, and the Identity Provider validates credentials. Then the IdP redirects the user back to HAProxy Enterprise SAML module.

  4. HAProxy Enterprise SAML module relays the user’s browser to the web application. An HTTP cookie ensures that the user will not need to log in again during their session.

Install for Microsoft Entra (formerly Azure Active Directory) Jump to heading

The single sign-on configuration described in this section uses Azure Active Directory as the Identity Provider. The HAProxy Enterprise SAML module is the Service Provider.

Create an Azure Active Directory enterprise application Jump to heading

To configure Azure Active Directory to serve as the Identity Provider for single sign-on:

  1. Sign in to the Azure portal.

  2. Search for and select Azure Active Directory. If you manage multiple Active Directory tenants, then choose Manage tenants and then select the tenant with which you would like to enable single sign-on.

  3. From the Azure Active Directory dashboard, choose Enterprise applications and then add a new application.

  4. On the Browse Azure AD Gallery screen, click Create your own application.

    • Give the app a name, such as samlapp
    • Choose Integrate any other application you don’t find in the gallery (Non-gallery)

    Then click Create.

    Azure enterprise application

  5. Click Assign users and groups. Choose users and groups that should get sign-on access to your application. Then return to the Overview screen.

  6. Click Set up single sign on, then choose SAML.

    The Set up Single Sign-On with SAML page opens. Edit the Basic SAML Configuration:

    Field Description
    Identifier (Entity ID) Choose a unique identifier for your application, such as samlapp.
    Reply URL (Assertion Consumer Service URL) Set the URL at which HAProxy Enterprise will receive the SAML authentication token. For example, https://example.com/saml/reply.
    Logout URL Set the URL at which HAProxy Enterprise will receive a logout message from Azure Active Directory. For example, https://example.com/saml/logout.

    Save and then close the basic SAML configuration panel.

  7. Still on the Set up Single Sign-On with SAML page, edit the SAML Certificates.

    For the Signing option choose Sign SAML response and assertion and set Signing Algorithm to SHA-256.

    Save and close the SAML Signing Certificate panel.

  8. You will need several properties of your Azure Active Directory enterprise application later when you configure HAProxy Enterprise. Save the following property values:

    Property Where to find it
    Name On the enterprise application’s Properties page.
    Application ID On the enterprise application’s Properties page.
    Tenant ID On the Azure Active Directory Overview page.

Configure the HAProxy Enterprise SAML module Jump to heading

  1. On your HAProxy Enterprise load balancer, install the SAML module via your system’s package manager.

    bash
    sudo apt-get install hapee-extras-spoa-saml
    bash
    sudo apt-get install hapee-extras-spoa-saml
    bash
    sudo yum install hapee-extras-spoa-saml
    bash
    sudo yum install hapee-extras-spoa-saml
    bash
    sudo zypper install hapee-extras-spoa-saml
    bash
    sudo zypper install hapee-extras-spoa-saml
    bash
    sudo pkg install hapee-extras-spoa-saml
    bash
    sudo pkg install hapee-extras-spoa-saml
  2. This creates the folder /etc/hapee-extras/saml_examples/azure. Copy the files from that folder to /etc/hapee-extras/. The files include:

    • authn_request.xml
    • logout_request.xml
    • saml.ini
  3. Edit the copied file saml.ini. At the top of the file, change the values of the following fields to match your Azure Active Directory enterprise application’s properties:

    Property Set it to
    {{ID_APP_NAME}} Your Azure AD enterprise application’s Name.
    {{IDP_APP_ID}} Your Azure AD enterprise application’s Application ID.
    {{IDP_TENANT_ID}} Your Azure Active Directory Tenant ID.
    {{APP_FQDN}} The fully qualified domain name where HAProxy Enterprise listens for requests, such as example.com. This should match the FQDN you used when setting the Reply URL and Logout URL in Azure. Be sure to add this record in your DNS server so that users can access your application at this domain.

    An example portion of the saml.ini configuration:

    saml.ini
    ini
    [MySAMLApp]
    {{ID_APP_NAME}} = samlapp
    {{IDP_APP_ID}} = 0fbb284d-39ea-4fc6-9639-114b46b8dcb3
    {{IDP_TENANT_ID}} = abcdefg-1234-5678-abcd-efgh12345678
    {{CLAIM_PREFIX}} = http://schemas.xmlsoap.org/ws/2005/05/identity/claims
    {{APP_FQDN}} = example.com
    {{APP_LOGIN_URL}} = https://{{APP_FQDN}}/saml/reply
    {{APP_LOGOUT_URL}} = https://{{APP_FQDN}}/saml/logout
    {{APP_BACKEND}} = bk-{{APP_NAME}}
    saml.ini
    ini
    [MySAMLApp]
    {{ID_APP_NAME}} = samlapp
    {{IDP_APP_ID}} = 0fbb284d-39ea-4fc6-9639-114b46b8dcb3
    {{IDP_TENANT_ID}} = abcdefg-1234-5678-abcd-efgh12345678
    {{CLAIM_PREFIX}} = http://schemas.xmlsoap.org/ws/2005/05/identity/claims
    {{APP_FQDN}} = example.com
    {{APP_LOGIN_URL}} = https://{{APP_FQDN}}/saml/reply
    {{APP_LOGOUT_URL}} = https://{{APP_FQDN}}/saml/logout
    {{APP_BACKEND}} = bk-{{APP_NAME}}

    Although the configuration in saml.ini defines only one SAML app named MySAMLApp, you can define multiple single sign-on apps. Copy all lines, except for the config_version line, and paste them below the existing lines, but replace MySAMLApp with a new name such as App2. Then change the properties to match your second application.

  4. Edit the HAProxy Enterprise configuration file, /etc/hapee-2.8/hapee-lb.cfg.

    Copy the SAML section below into the frontend section for your load balanced application. Modify the line that sets the variable sess.saml_app to match the app name in saml.ini (for example, MySAMLApp), and change the if statement to use your fully qualified domain name. The rest does not need to be changed.

    Below, we add the directives to enable SAML single sign-on in the frontend:

    hapee-lb.cfg
    haproxy
    frontend fe_main
    bind :80
    bind :443 ssl crt /etc/hapee-2.8/ssl/cert.pem
    mode http
    option http-buffer-request
    tcp-request inspect-delay 5s
    # --------------------
    # ----SAML section----
    # --------------------
    # here, replace MySAMLApp and the if statement with correct FQDN, depending on your setup
    http-request set-var(sess.saml_app) str(MySAMLApp) if { hdr(host) -i example.com }
    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-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 }
    # ------------------------
    # ----end SAML section----
    # ------------------------
    # The backend to send authenticated requests to
    default_backend webservers
    hapee-lb.cfg
    haproxy
    frontend fe_main
    bind :80
    bind :443 ssl crt /etc/hapee-2.8/ssl/cert.pem
    mode http
    option http-buffer-request
    tcp-request inspect-delay 5s
    # --------------------
    # ----SAML section----
    # --------------------
    # here, replace MySAMLApp and the if statement with correct FQDN, depending on your setup
    http-request set-var(sess.saml_app) str(MySAMLApp) if { hdr(host) -i example.com }
    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-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 }
    # ------------------------
    # ----end SAML section----
    # ------------------------
    # The backend to send authenticated requests to
    default_backend webservers
  5. Add a backend section for the SAML module service. HAProxy Enterprise uses this when authenticating requests.

    Below, we add a backend for the SAML module service:

    hapee-lb.cfg
    haproxy
    backend bk-spoe
    mode tcp
    timeout connect 5s
    timeout server 30s
    server auth-server-spoe 127.0.0.1:12345
    hapee-lb.cfg
    haproxy
    backend bk-spoe
    mode tcp
    timeout connect 5s
    timeout server 30s
    server auth-server-spoe 127.0.0.1:12345
  6. Enable and start the SAML module service.

    bash
    sudo systemctl enable hapee-extras-spoa-saml
    sudo systemctl start hapee-extras-spoa-saml
    bash
    sudo systemctl enable hapee-extras-spoa-saml
    sudo systemctl start hapee-extras-spoa-saml
  7. Restart the HAProxy Enterprise service.

    bash
    sudo systemctl restart hapee-2.8-lb
    bash
    sudo systemctl restart hapee-2.8-lb

    You can then make requests to your application and you will be redirected to the Azure login page.

Optional: Verify the signature of the SAML Response Jump to heading

When Azure sends its SAML response that contains the information HAProxy Enterprise needs to authorize a user to access an application, it is sending an XML token. To prove that it is the trusted issuer of that token, it digitally signs it with its secret key. You can verify that key using the key’s associated public X.509 certificate.

To enable signature verification:

  1. Sign in to the Azure portal.

  2. Search for and select Azure Active Directory. If you manage multiple Active Directory tenants, then choose Manage tenants and then select the tenant with which you would like to enable single sign-on.

  3. From the Azure Active Directory dashboard, choose Enterprise applications, select your application, then select Single sign-on in the left-hand menu.

  4. From the Set up Single Sign-On with SAML screen, edit the SAML Certificates. Ensure that Signing Option is set to Sign SAML response and assertion and that Signing Algorithm is set to SHA-256.

  5. From the SAML Certificates section, download the certificate (Base64 format). This downloads a file with a .cer extension. Copy this file to your HAProxy Enterprise load balancer, such as to /etc/hapee-extras/.

  6. On the HAProxy Enterprise server, edit the file /etc/hapee-extras/saml.ini.

    Uncomment (remove the preceding semicolon) the lines idp_public_cert and verify_signature. Set idp_public_cert to the path of the certificate from your Azure Active Directory enterprise application.

    Below, we enable signature verification using your application’s certificate:

    saml.ini
    ini
    idp_public_cert = /etc/hapee-extras/samlapp.cer
    verify_signature=1
    saml.ini
    ini
    idp_public_cert = /etc/hapee-extras/samlapp.cer
    verify_signature=1
  7. Restart the SAML service.

    bash
    sudo systemctl restart hapee-extras-spoa-saml
    bash
    sudo systemctl restart hapee-extras-spoa-saml

Log out Jump to heading

Users can log out of your application by visiting the /saml/logout URL path, such as https://example.com/saml/logout. This will send a LogoutRequest to Azure Active Directory, and then Azure will send the user back to the application for local logout of the app.

If users have chosen the Keep Me Signed In option when logging in, this may affect the logout flow.

Troubleshooting Jump to heading

Some steps to aid in troubleshooting:

  • Check the status of the SAML module service, which will show any errors it encountered while validating SAML responses.

    bash
    sudo systemctl status hapee-extras-spoa-saml.service
    bash
    sudo systemctl status hapee-extras-spoa-saml.service
  • In order to perform troubleshooting, the SAML module can be launched in full debug mode.

    bash
    systemctl stop hapee-extras-spoa-saml.service
    /opt/hapee-extras/bin/hapee-saml -F -f /etc/hapee-extras/saml.ini --debug-all
    bash
    systemctl stop hapee-extras-spoa-saml.service
    /opt/hapee-extras/bin/hapee-saml -F -f /etc/hapee-extras/saml.ini --debug-all

SAML configuration reference Jump to heading

This sections describes the syntax of the file /etc/hapee-extras/saml.ini.

Directives Jump to heading

The /etc/hapee-extras/saml.ini file configures how HAProxy Enterprise integrates with the SAML identity provider. It supports the following configuration directives.

Directive Description Type
idp_login_url URL of the Web authentication portal of the Identity Provider. On Microsoft Azure, https://login.microsoftonline.com/{{IDP_APP_ID}}/saml2. string
config_version The version of the configuration file. Maintains compatibility with future versions. string
idp_logout_url Single Logout URL: Endpoint which initiates the SAML Logout for all applications. On Microsoft Azure, https://login.microsoftonline.com/logout.srf. string
idp_referer_url HTTP Referer value to check when receiving HTTP data from the Identity Provider. On Microsoft Azure, https://login.microsoftonline.com/. string
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 (ACS). string
app_logout_url When the user browses this URL, initiate a LogoutRequest to the Identity Provider. string
signing_algo Cryptographic algorithm used to sign the requests we send. string
idp_public_cert X509 public cert of the Identity Provider (in base64 form, .pem) used to verify SAML Response Response and Assertion attributes. string
verify_signature Verify the signature of incoming SAML requests. Default: 0 boolean
require_signed_response Fail if the XML response is not signed. Default: 0 boolean
require_signed_assertion Fail if the XML assertion is not signed. Default: 0 boolean
signing_key Private key used to sign requests we send. string
sign_authn_requests Set to 1 if you want to sign Authn Requests. Default: 0 boolean
sign_logout_requests Set to 1 if you want to sign LogoutRequest requests. Default: 0 boolean
saml_app_backend Backend name for this application. Default: bk-{{APP_NAME}} string
saml_cookie_secure Set to 1 if you want cookies to be used for HTTPS connections only (not HTTP). Default: 0 boolean
saml_cookie_samesite SameSite cookie attribute value. string
saml_cookie_httponly HttpOnly cookie attribute value. Default: 1 boolean
saml_cookie_time_offset Cookie time offset in seconds (used to build Expires cookie attribute). Default: 0 integer
saml_cookie_lifetime Cookie lifetime in seconds (used to build Expires cookie attribute). Default: 36000 integer
saml_cookie_domain Domain cookie attribute value. string
authn_request_template_filename Authn Request template filename. string
logout_request_template_filename LogoutRequest template filename. string

Actions Jump to heading

In the /etc/hapee-extras/saml.ini file, actions let you validate the schema, set variables, and other tasks.

Action Description
on_saml_response check_attr Check an arbitrary attribute in a SAML Response. To store the attribute value in an HAProxy Enterprise variable txn.my_var_name, use XPath= set_var=. To set per application variables, use set_var=({{APP_NAME}}.my_var_name. {{APP_NAME}} is replaced with the application name (ie the section name in saml.ini). The SAML Response validation fails if an attribute is not present, except if you set the optional flag.
on_saml_response check_attr entity_id Check that the audience attribute exists. The specific entity_id value to check in required.
on_saml_response check_attr version Check that SAML protocol version is 2.0.
on_saml_response check_attr status_code Check the SALMResponse status code. The status to match, status_code, is optional. 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. destination is required. To match the configured app_login_url, use <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. The specific issuer value to check is optional.
on_saml_response check_attr issue_instant Check that the IssueInstant attribute exists. To store it in a variable, use set_var. To store it in a timestamp variable, use set_var_as_timestamp.
on_saml_response check_attr assertion Check that the Assertion attribute exists.
on_saml_response check_schema Validate the SAML response against the SAML 2.0 xsd schema.
on_saml_response check_conditions Check the XML attribute, including NotBefore and NotOnOrAfter values.
on_saml_response check_subject_confirmation_data Check the XML attribute, including NotBefore and NotOnOrAfter values.
on_logout_request check_attr Check an arbitrary attribute in a LogoutRequest. To put it in an HAProxy Enterprise variable, use XPath= set_var=.
on_logout_request check_attr issuer Check the issuer attribute of the LogoutRequest. The specific issuer value to check is optional.
on_logout_request check_attr name_id Check that the nameId attribute exists in the LogoutRequest.
on_logout_request check_attr destination Check that the LogoutRequest Destination value matches this item. The destination to match is required. To match the configured app_logout_url, use <APP_LOGOUT_URL>.

Action flags Jump to heading

Actions accept the following flags:

Flag Description
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> Fail 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> Fail if the result is different from this expression.
set_var=<var_name> When one or more XPath results are found, store its value in this specific variable. The variable name is prefixed with the application name, then with a dot.
set_var_once The variable is set only after the POST from the SAML Identity Provider. Otherwise, it is set each time we see the cookie again.
set_var_cnt The number of XPath results is stored in the variable <APP_NAME>.<VAR_NAME>_cnt.
set_var_as_timestamp When used with a value in ISO 8601 date and time format (for instance 2020-01-28T15:25:14.884Z), the variable is converted to a timestamp.
set_var_sep=<separator> When 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.

If this page was useful, please, Leave the feedback.