Single sign-on

Single sign-on (Kerberos)

The HAProxy Enterprise Single Sign-On solution allows you to set up SSO on a Microsoft Active Directory domain. It uses the Kerberos protocol for authentication and is compatible with Microsoft Active Directory and OpenLDAP servers. It is composed of a set of configuration files, and a program called spoa-sso, which talks to HAProxy Enterprise using the SPOE (Stream Processing Offload Engine) protocol.

SSO allows you to:

  • Implement access control to applications on your network, even if the applications themselves do not support authentication or the Kerberos protocol.
  • Implement access control and identity delegation to your internal applications, from an external network or from a VPN.
  • Provide single sign-on ability in a Microsoft Active Directory domain.

Install the HAProxy Enterprise SPOA module Jump to heading

The HAProxy Enterprise SPOA SSO service is distributed as a package for all Linux distributions that support HAProxy Enterprise.

If you use a Debian based system, type the following command to install the solution:

nix
sudo apt-get install hapee-extras-spoa-sso
nix
sudo apt-get install hapee-extras-spoa-sso
nix
sudo yum install hapee-extras-spoa-sso
nix
sudo yum install hapee-extras-spoa-sso
nix
sudo zypper install hapee-extras-spoa-sso
nix
sudo zypper install hapee-extras-spoa-sso
nix
sudo pkg install hapee-extras-spoa-sso
nix
sudo pkg install hapee-extras-spoa-sso

Terms Used Jump to heading

The SSO solution allows users to access different resources and applications, depending on their rights.

  • In a Microsoft environment, users of an organization are part of a domain.
  • Active Directory is a set of services that provide authentication, identification, and management of users of a domain.

Active Directory also deals with these protocols within the domain:

  • DNS
  • LDAP
  • Kerberos

If you use Microsoft Active Directory, it becomes a central part of the SSO solution. Hence, you must set it up correctly for proper operation. See Active Directory documentation for information.

Kerberos protocol Jump to heading

This SSO solution optionally implements the S4U (services for user) extensions from Microsoft that allow enhanced security and user impersonation. It supports SPNEGO negotiation mechanism.

DNS Protocol Jump to heading

To successfully use the Kerberos protocol, you must observe some requirements regarding the DNS configuration:

  • The server running the SSO agent must have a proper hostname that can be resolved to an IP, using DNS.

  • You can also modify your /etc/hosts file.

  • The IP address of the Kerberos KDC is retrieved via DNS, using _kerberos service.

  • If you cannot configure your DNS server, you must specify the KDC in /etc/krb5.conf.

  • The reverse DNS must also work. If not, you must add /etc/krb.conf to disable the reverse DNS:

    krb.conf
    ini
    [libdefaults]
    rdns = false
    krb.conf
    ini
    [libdefaults]
    rdns = false

SPOE protocol and SSO agent Jump to heading

The SSO agent uses the Stream Processing Offload Engine protocol (SPOA). The SSO agent runs as a separate process. Each HTTP request and response is passed to the SSO agent which checks if the user is allowed to access the requested resource and determines whether to:

  • Allow
  • Deny
  • Present the authentication form

Life of a request:

Single Sign On flowchart 1

Life of a response:

Single Sign On flowchart 2

Use the provided built-in Web portal Jump to heading

If you use the default built-in Web portal, you can customize your company logo and your CSS file.

The location of these files is:

  • <HAPEE_DIR>/sso/portal/logo.png (or logo.jpg)
  • <HAPEE_DIR>/sso/portal/css.css

Implement a custom Web portal Jump to heading

To implement a Web portal that displays a login form to the user, you only need a simple Web server that handles the HTTP headers sent by the load balancer.

SSO headers Jump to heading

Header Description
X-SSO-ACTION An action that can be any of the following: frm: display the authentication form to the user, fOK: display the login confirmation page: You now have access to application app, lOK: display the logout confirmation page: You have been logged out, dny: access denied, err: an error occurred.
X-SSO-MSG A message to display to the user.
X-SSO-DOMAIN The domain.
X-SSO-APP The application that the user wants to access. It is determined by the URL and the SSO agent.
X-SSO-TITLE-PAGE The main URL of the application. The web server can include a link to this page to lead the user directly to the application.
X-SSO-LOGIN If set_login option is set to 1, this header will contain the user login.
X-SSO-REDIR_QS This header redirects users to the page they want to access before being redirected to the authentication portal. If this header is set, the server must include its content into the form the user will POST. For example, you can add a hidden field. This field must be called posted_redir.
X-SSO-REDIR_URL Contains the URL that users want to access. You can redirect them to this URL after a successful authentication.

Establish an authentication form Jump to heading

This HTML page must contain an HTML form to allow the user to enter his login and password and to select the domain to log on.

The POST action must be able to post on the same URL.

A minimal form could be the following:

example.html
html
<form method="POST">
<input name="login" />
<input name="password" />
<select name="domain">
<option value="mydomain.net">My Domain</option>
</select>
<!-- optional field. It should contain the value extracted from the
X-SSO-REDIR_QS header -->
<input type="hidden" name="posted_redir" values="..." />
</form>
example.html
html
<form method="POST">
<input name="login" />
<input name="password" />
<select name="domain">
<option value="mydomain.net">My Domain</option>
</select>
<!-- optional field. It should contain the value extracted from the
X-SSO-REDIR_QS header -->
<input type="hidden" name="posted_redir" values="..." />
</form>

The POST is done on the form backend and handled by the load balancer, which extracts the information and passes it on to the SSO agent.

Add SSO ability to an application Jump to heading

After you set up SSO, use the following procedure to add more applications:

  1. Add a new domain:

    • You must add the new domain in a Web form of an HTML page. The user must be able to select it, and you must include its value in the POST.
  2. To add an application if you use Kerberos with an Active Directory:

    • Add a new service user associated with the service principal name (SPN) of your application.

    • Create a new Keytab for the new SPN or add it to an existing Keytab.

      On Windows:

      powershell
      ktpass /out myapp.keytab /mapuser <service-user>MYDOMAIN.NET /princ HTTP/myapp.mydonain.net@MYDOMAIN.NET /pass <PASSWORD>
      powershell
      ktpass /out myapp.keytab /mapuser <service-user>MYDOMAIN.NET /princ HTTP/myapp.mydonain.net@MYDOMAIN.NET /pass <PASSWORD>
  3. Update the keytab_file directive, if needed.

  4. Add the application to conf/sso.map.

  5. In the configuration file sso.ini, add the application section and attach it to the correct domain.

  6. Add the specified backend to hapee-lb.cfg.

  7. To check if a user is allowed to access an application, you must check that the X-SSO-* headers are as follows:

    • X-SSO-APP: <name of the application>
    • X-SSO-DOMAIN: <name of the domain>
    • X-SSO-ACTION: alw
    • X-SSO-LOGIN: <user login>

Configure SSO Jump to heading

The single sign-on (SSO) function requires several configuration files.

The file haproxy-sso.cfg defines the main HTTP frontend that HTTP clients require in order to use SSO.

It also defines the HTTP rules, ACLs, and checks involved between the SPOE agent and the load balancer.

You may have to modify parts of this file depending on your Active Directory setup and your network configuration.

  • The bind directive of the frontend: bind *:80

  • The sso_portal backend:

    • If you use your own external Web server to host the SSO portal, use:

      haproxy
      backend sso_portal
      # this is the webserver used to diplay the SSO login form
      mode http
      server sso_portal-1 my_web_server:80
      haproxy
      backend sso_portal
      # this is the webserver used to diplay the SSO login form
      mode http
      server sso_portal-1 my_web_server:80
    • If you want to use the built-in LUA Web server, use:

      haproxy
      global
      lua-load sso_portal.lua
      backend sso_portal
      mode http
      http-request use-service lua.sso_portal
      haproxy
      global
      lua-load sso_portal.lua
      backend sso_portal
      mode http
      http-request use-service lua.sso_portal

Configure SSO SPOE Jump to heading

The haproxy-sso-spoe.cfg file contains information regarding which messages to exchange between the SSO SPOE daemon and the load balancer.

We recommend that you do not modify it and keep it as provided.

Specify SSO mappings Jump to heading

The file sso.map must contain the mappings between your different applications and the Host header.

sso.map
ini
# Host header <domain>/<app>
sp2010.mydomain.net 2010.mydomain.net/sharepoint2010
sp2013.mydomain.net 2013.mydomain.net/sharepoint2013
exchange2013.mydomain.net 2013.mydomain.net/exchange2013
stats.mydomain.net stats/stats
sso.map
ini
# Host header <domain>/<app>
sp2010.mydomain.net 2010.mydomain.net/sharepoint2010
sp2013.mydomain.net 2013.mydomain.net/sharepoint2013
exchange2013.mydomain.net 2013.mydomain.net/exchange2013
stats.mydomain.net stats/stats

Configure the SSO daemon Jump to heading

The sso.ini file is the main configuration file of the SSO daemon. It must contain information about each application that you want to manage.

It uses a similar syntax to any typical Windows .ini file.

  • Lines starting with ; or # are comments.

  • Comments can appear at the end of any line when preceded by a space.

  • There are several sections in sso.ini:

    • The default section ([defaults]) contains default values. These values are inherited by each domain.

    • Domain sections ([domain:mydomain]) define properties valid for the scope of the entire domain.

    • Other sections are applications sections.

  • At least one domain section is required, and each application must be attached to exactly one domain. Applications inherit the properties of their domain, and can also override them.

  • Some properties can include keywords within brackets such as <KRB_REALM> that get replaced with appropriate values at run time. For example, if you prefer that all your backends start with bk_, you can use:

sso.ini
ini
backend = bk_<APP_NAME>
sso.ini
ini
backend = bk_<APP_NAME>
Configuration directives
Directive Description
[application_name] Each application must have a unique name. To name applications, you may use alphanumeric characters or underscores. This name must match a name in the sso.map file.
internal_domain The internal host name of your application. It must match the domain part of the Kerberos SPN (ie HTTP/mydomain.int).
external_domain The external FQDN of your application.
krb_auth_method When setting this field to 1, the load balancer authenticates the user with the information provided in the login form. This is the method we recommend, in addition to krb_s4u = 1 that uses Kerberos constrained delegation.
krb_cache_name Allows you to choose the location of the Kerberos tickets cache: on disk: /tmp/kr5cc_<USER>, in memory: MEMORY:kr5cc_<USER>.
sso_cookie_domain Defines the domain attribute that the SSO agent must use when setting its cookie. You must match the longest common part of your external host name. sso_cookie_lifetime: Defines the lifetime of the SSO cookie (in seconds). Past this time, the user must reauthenticate. Default: 36000s.
sso_cookie_lifetime Defines the lifetime of the SSO cookie (in seconds). Past this time, the user must reauthenticate. Default: 36000s.
ldap_uri For each domain, you must define additional LDAP and Kerberos parameters as follows: ldap://ad.mydomain.net. The LDAP server validates the credentials from the user, and refreshes all groups to which the user belongs. The load balancer refreshes a group membership every ldap_groups_refresh_interval seconds, and it can use a different user/password specified in ldap_groups_refresh_user and ldap_groups_refresh_password. ldap_base, such as dc=mydomain,dc=net. krb_realm contains your Kerberos realm (usually in upper case). krb_keytab_file defines the Keytab file that contains Kerberos services you want to use.
ldap_auth_start_tls Controls whether to use TLS when connecting to the LDAP server: 0:disabled, 1:enabled (by default)
internal_domain, external_domain Must be defined for each application.
auth_url Indicates the URLs to reach the login. When users must enter their credentials, the load balancer redirects them here. After a successful authentication, a message displays with a link to access the application. You can use title_page to define the target of the link. If your application runs on a non-standard port, you have to specify it in auth_url. For instance, if your application runs on port 8080, specify auth_url = <EXTERNAL_DOMAIN>:8080/auth.
logout_url An authenticated user who reaches this URL gets logged out.
title_page After a successful authentication, a message displays with a link to access the application. You can use title_page to define the target of the link. You must use an absolute URL with the scheme (HTTP or HTTPS). Example: the URL for a standard Sharepoint2013 installation can be: https://<EXTERNAL_DOMAIN>/SitePages/Home.aspx.
redir_url_encoding_secret Secret used to encode the current user URL, and to redirect the user after a successful authentication. If you load-balance the SSO portal, you must share the secret among the different servers. Otherwise, use <RANDOM> to generate a random secret upon launch, or <DISABLED> to disable the redirections.
ldap_required_group Use this directive to restrict access to a particular application to a specified group of users. The group must have the following form: CN=Builtin,DC=2013,DC=mydomain,DC=net. The load balancer performs the matching using the memberOf attribute, which is case insensitive.
allow_unauthenticated_users By default, all applications require the user to log into the corresponding domain and a valid cookie to grant access. This directive allows access to certain applications without any access check. If set to 1, the load balancer allows access without any access check.
set_login If set to 1, sets the X-SSO-LOGIN header with the user login. Default: 0.
ldap_groups_membership_attribute LDAP member to search for when computing LDAP groups membership (default: memberOf)
ldap_groups_search_filter LDAP filter to apply when computing LDAP groups membership (default: sAMAccountName=<LOGIN>)

Troubleshooting Jump to heading

  • LDAP and Kerberos issues

    The SSO solution does not require the file /etc/krb5.conf, but you can use it if the file is present in order to override default values or define a specific set of ciphers. Refer to the MIT Kerberos documentation for more information.

    To troubleshoot your environment, you can perform the following tasks:

    • Set the environment variable KRB5_TRACE to a log file, or to /dev/stdout to get more verbose Kerberos diagnostics. In addition, you can pass the --debug-krb flag to the SSO daemon.
    • Use the provided tool called sso-diag to test parts of the workflows involved when working with Kerberos.
    • Test ticket creation in Kerberos using: ./sso-diag -f sso.ini -a MYAPP -d MYDOMAIN -u USER -p PASSWORD krb_ticket
    • Check that your access rules or required LDAP groups are set and configured correctly by launching: ./sso-diag -f sso.ini -a MYAPP -d MYDOMAIN -u USER -p PASS auth and replacing MYAPP, MYDOMAIN, USER, and PASS with appropriate values. This directive simulates a user doing a POST on the authentication form with the supplied credentials.
    • You can also use ./sso-diag -f sso.ini -a MYAPP -d MYDOMAIN -A MYAPP2 -D MYDOMAIN2 -u USER -p PASS check to simulate a POST with the supplied credentials on MYAPP on MYDOMAIN, and then try to access MYAPP2 on MYDOMAIN2.
    • Get the status of the different worker threads running on the SSO agent by sending a SIGUSR1 at any time (when launched with --debug-all).
  • HTTP 503 error

    • If you get a 503 error (service unavailable) coming from the load balancer, launch the agent with the --debug-spoe-variables option.

    • If the SSO application granted access to the URL, check that your backend is correctly configured in hapee-lb.cfg.

    • For example, if you get any of the following messages, check that the POC backend exists in the file hapee-lb.cfg:

      text
      Encode SPOE set-var str scope=1 sso_app=poc
      Encode SPOE set-var str scope=1 sso_domain=poc
      Encode SPOE set-var str scope=1 action=alw
      Encode SPOE set-var str scope=2 backend=poc
      text
      Encode SPOE set-var str scope=1 sso_app=poc
      Encode SPOE set-var str scope=1 sso_domain=poc
      Encode SPOE set-var str scope=1 action=alw
      Encode SPOE set-var str scope=2 backend=poc
  • Configuration errors

    • Invalid domain xxx: ‘cannot match config’: This means that the domain, which was set using sso.map by matching the host header, has no corresponding section in sso.ini.

    • ‘No authentication info found’ displays repeatedly while logging on the form: If you get this error, check the sso_cookie_domain directive in sso.ini. The sso_cookie_domain must match the domain of your applications. When logging in with correct credentials, you should see a response header similar to this:

      text
      Set-Cookie: sso-cookie=abc122342; domain=mydomain.net
      text
      Set-Cookie: sso-cookie=abc122342; domain=mydomain.net
  • No server contact error

    • ‘Cannot contact server’ or ‘error in start_tls()’: Check that you configured your DNS correctly, and that you can reach the LDAP server on the correct port (standard ports are 636 or 389 depending on the configuration).
  • Failure to connect with LDAP server

    • ‘TLS or SSL already in effect’: You cannot use a ldaps:// URL and a ldap_auth_start_tls set to 1 at the same time. They are mutually exclusive.
  • GnuTLS error

    • ‘GnuTLS: A TLS packet with unexpected length was received’: You may get this error on servers where an old version of the GnuTLS or OpenSSL library was installed. You can change the ciphers used by LDAP libraries with environment variables. For instance:

      text
      export LDAPTLS_CIPHER_SUITE='NORMAL:!VERS-TLS1.2'
      text
      export LDAPTLS_CIPHER_SUITE='NORMAL:!VERS-TLS1.2'
  • SSL certificate error

    • ssl3_get_server_certificate:certificate verify failed (unable to get local issuer certificate): You can bypass the LDAP certificates verification by using the -N flag. This sets the environment variable LDAPTLS_REQCERT to never
  • Host/domain error

    • gss_acquire_cred_impersonate_name: host/domain name not found’: The host name of the server running the SSO agent must resolve to an IP. Add it to your DNS server or in your hosts file.
  • DNS issues

    • gss_init_sec_context failed, major_stat=851968, minor_stat=100006: Reverse DNS must work on the server running the SSO agent. You must be able to resolve your server IP to its host name. If not, you can add this /etc/krb.conf, to disable the reverse DNS:

      krb.conf
      ini
      [libdefaults]
      rdns = false
      krb.conf
      ini
      [libdefaults]
      rdns = false

See also Jump to heading

Do you have any suggestions on how we can improve the content of this page?