Single sign-on
Single sign-on (AD FS Web Proxy)
Available since:
- HAProxy Enterprise 3.1r1
This ADFSPIP module enables HAProxy Enterprise to serve as a reverse proxy in front of your Active Directory Federation Services (AD FS) federation server. AD FS authenticates users so that they can access web applications running inside your corporate network. HAProxy Enterprise gives clients outside your corporate network access to those web applications, after they’ve signed in via AD FS. You will typically deploy HAProxy Enterprise at the edge of your network where external clients can access it.
Using HAProxy Enterprise as a web proxy in front of AD FS serves the same job as and replaces the Web Application Proxy on Windows Server. The module uses the Active Directory Federation Services and Proxy Integration Protocol to communicate with AD FS.
Essential concepts include:
- Upon startup, HAProxy Enterprise connects to your AD FS federation server and establishes a trust relationship.
- When HAProxy Enterprise receives an HTTP requests from an unauthenticated client, it redirects the client to the federation server URL to sign in. Because external clients won’t have direct access to the federation server, this request will go through HAProxy Enterprise. As such, you’ll need to configure split-brain DNS so that the federation server URL points to HAProxy Enterprise for external clients, but to the true AD FS server for internal clients.
- After successful sign in through AD FS, the client returns with an authentication token to the web application URL it originally requested.
- HAProxy Enterprise validates the authentication token using the AD FS server’s token signing certificate. It then relays the client’s requests to the web application.
- You must publish each web application for which you want to enable AD FS authentication. Publishing entails adding the application as a Relying Party Trust in AD FS, which adds it to the list of proxied services.
Prerequisites Jump to heading
Please check that you’ve met the following prerequisites:
-
You’re running Windows Server 2016 or later.
-
Your Windows Server has the Active Directory Domain Services role and has created an Active Directory forest. See the Windows Server guide Install Active Directory Domain Services.
-
Your Windows Server has the Active Directory Federation Services (AD FS) role. See the Windows Server guide Install the AD FS Role Service.
Use a wildcard certificate
While configuring AD FS, you’ll be asked to select an SSL certificate. To reduce the number of certificates, consider buying a wildcard certificate that will match all of your subdomains. It would have a CN value like
*.example.com
. -
Optional: If you plan to use this server as a DNS server, add the DNS role. See the Windows Server guide Installing DNS Server.
Installation and setup Jump to heading
In this section, you’ll learn how to install and set up the module.
1. Configure split-brain DNS Jump to heading
To access web applications, users will sign in via the AD FS federation server’s sign-in page at a URL like https://adfs.example.com/adfs/ls?version=1.0&action=signin
. That domain name should resolve to an IP address belonging to HAProxy Enterprise so that the load balancer can proxy the sign-in requests.
Configure your DNS server for split-brain DNS so that the domain name resolves differently for internal and external clients. Learn more in the Windows Server guide Use DNS Policy for Split-Brain DNS Deployment.
- HAProxy Enterprise should resolve the federation server’s domain name, for example
adfs.example.com
, to the internal IP address of the AD FS server. Later, you’ll see how to configure aresolvers
section in your HAProxy Enterprise configuration to use your DNS nameserver. - External clients should resolve the domain name, again
adfs.example.com
, to the public IP address of HAProxy Enterprise. - External clients should resolve the web application’s external URL, such as
www.example.com
to the public IP address of HAProxy Enterprise.
For testing purposes, you can simply set the hosts
file on the client.
2. Collect certificates Jump to heading
The AD FS server has certificates that you’ll need to copy to your HAProxy Enterprise server before it can function as a web proxy in front of AD FS. You’ll get these certificates:
Certificate | Description |
---|---|
Token signing certificate | The federation server uses this certificate’s associated public/private key pair to digitally sign all authentication tokens that it produces. HAProxy Enterprise needs only the public key to validate tokens. |
Client certificate | HAProxy Enterprise authenticates to the federation server by presenting this certificate. |
On the AD FS server:
-
Get the token signing certificate, which the AD FS server uses to digitally sign authentication tokens it produces. HAProxy Enterprise will use the public key portion of the certificate to validate the authentication tokens, also known as JSON Web Tokens (JWT), that clients receive from AD FS after authenticating.
-
Open Server Manager and go to Tools > AD FS Management.
-
Expand Service and select Certificates.
-
Right click the
ADFS Signing
certificate and select View certificate. -
From the Details tab of the Certificate dialog, select Copy to File.
-
Use the Certificate Export Wizard to export the certificate as a DER encoded binary X.509 (.CER) file. You don’t need to export its private key.
-
Transfer this file to the HAProxy Enterprise server and place it in a directory such as
/etc/hapee-3.1/adfs-signing-cert.cer
. -
Convert the file to the PEM format:
nixsudo openssl x509 -inform der -in adfs-signing-cert.cer -out adfs-signing-cert.pemnixsudo openssl x509 -inform der -in adfs-signing-cert.cer -out adfs-signing-cert.pem -
Extract the public key from the PEM file:
nixopenssl x509 -pubkey -noout -in ./adfs-signing-cert.pem | sudo tee adfs-signing-pubkey.pemnixopenssl x509 -pubkey -noout -in ./adfs-signing-cert.pem | sudo tee adfs-signing-pubkey.pemAuto-rotated certificates
By default, AD FS rotates the token signing certificate after an interval, which means you’ll need to repeat this process routinely. You can change the rotation interval or disable this feature and manage the rotation manually. To learn more, see the Windows guide Obtain and configure TS and TD certificates for AD FS.
-
-
Each time that HAProxy Enterprise relays a client to the AD FS sign-in page, it must attach its own client certificate so that the connection will be accepted. To generate a client certificate, first create a CA certificate for your organization that you’ll use to sign client certificates. Use the
New-SelfSignedCertificate
PowerShell command to create a CA certificate for your organization. Here, we create a self-sign CA certificate, save it to the local computer’s My store, then export it as a file:powershell$ca = New-SelfSignedCertificate -Type Custom `-KeySpec Signature `-Subject "CN=Example CA" `-KeyExportPolicy Exportable `-HashAlgorithm sha256 `-KeyLength 2048 `-CertStoreLocation cert:\LocalMachine\My `-KeyUsageProperty Sign `-KeyUsage CertSign `-NotAfter (Get-Date).AddMonths(120)$password = ConvertTo-SecureString -String "P@ssword12345" -Force -AsPlainTextExport-PfxCertificate -Cert $ca -FilePath C:\example-ca.pfx -Password $passwordpowershell$ca = New-SelfSignedCertificate -Type Custom `-KeySpec Signature `-Subject "CN=Example CA" `-KeyExportPolicy Exportable `-HashAlgorithm sha256 `-KeyLength 2048 `-CertStoreLocation cert:\LocalMachine\My `-KeyUsageProperty Sign `-KeyUsage CertSign `-NotAfter (Get-Date).AddMonths(120)$password = ConvertTo-SecureString -String "P@ssword12345" -Force -AsPlainTextExport-PfxCertificate -Cert $ca -FilePath C:\example-ca.pfx -Password $password -
Import the CA certificate into the Client Authentication Issuers certificate store:
powershell$password = ConvertTo-SecureString -String "P@ssword12345" -Force -AsPlainTextImport-PfxCertificate -FilePath C:\example-ca.pfx -CertStoreLocation cert:\LocalMachine\ClientAuthIssuer -Exportable -Password $passwordpowershell$password = ConvertTo-SecureString -String "P@ssword12345" -Force -AsPlainTextImport-PfxCertificate -FilePath C:\example-ca.pfx -CertStoreLocation cert:\LocalMachine\ClientAuthIssuer -Exportable -Password $password -
Create a client certificate and sign it with the CA certificate you just created:
powershell$client = New-SelfSignedCertificate -Type Custom `-KeyUsage DigitalSignature `-Subject "CN=HAProxy Enterprise" `-KeyExportPolicy Exportable `-HashAlgorithm sha256 `-KeyLength 2048 `-CertStoreLocation cert:\LocalMachine\My `-Signer $ca `-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2") `-NotAfter (Get-Date).AddMonths(120)$password = ConvertTo-SecureString -String "P@ssword12345" -Force -AsPlainTextExport-PfxCertificate -Cert $client -FilePath C:\client.pfx -Password $passwordpowershell$client = New-SelfSignedCertificate -Type Custom `-KeyUsage DigitalSignature `-Subject "CN=HAProxy Enterprise" `-KeyExportPolicy Exportable `-HashAlgorithm sha256 `-KeyLength 2048 `-CertStoreLocation cert:\LocalMachine\My `-Signer $ca `-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.2") `-NotAfter (Get-Date).AddMonths(120)$password = ConvertTo-SecureString -String "P@ssword12345" -Force -AsPlainTextExport-PfxCertificate -Cert $client -FilePath C:\client.pfx -Password $password -
Transfer the
client.pfx
file to the HAProxy Enterprise server and convert it to a PEM file:nixsudo openssl pkcs12 -in ./client.pfx -out ./client.pem -nodesnixsudo openssl pkcs12 -in ./client.pfx -out ./client.pem -nodes
3. Establish a connection Jump to heading
HAProxy Enterprise must connect to the AD FS server and use Active Directory credentials to form a trust relationship.
On the AD FS server:
-
If you previously deployed a Web Application Proxy, remove the relying party trust it created by opening a PowerShell terminal as an administrator and running this command:
powershellRemove-AdfsWebApplicationProxyRelyingPartyTrustpowershellRemove-AdfsWebApplicationProxyRelyingPartyTrust -
Create a new web application proxy relying party trust for HAProxy Enterprise:
powershellAdd-AdfsWebApplicationProxyRelyingPartyTrust -Identifier haproxy-enterprise -Name haproxy-enterprisepowershellAdd-AdfsWebApplicationProxyRelyingPartyTrust -Identifier haproxy-enterprise -Name haproxy-enterprise
On the HAProxy Enterprise server:
-
Install the ADFSPIP module according to your platform:
nixsudo apt-get install hapee-<VERSION>-lb-adfspipnixsudo apt-get install hapee-<VERSION>-lb-adfspipExample for HAProxy Enterprise 3.1r1:
nixsudo apt-get install hapee-3.1r1-lb-adfspipnixsudo apt-get install hapee-3.1r1-lb-adfspipnixsudo yum install hapee-<VERSION>-lb-adfspipnixsudo yum install hapee-<VERSION>-lb-adfspipExample for HAProxy Enterprise 3.1r1:
nixsudo yum install hapee-3.1r1-lb-adfspipnixsudo yum install hapee-3.1r1-lb-adfspipnixsudo zypper install hapee-<VERSION>-lb-adfspipnixsudo zypper install hapee-<VERSION>-lb-adfspipExample for HAProxy Enterprise 3.1r1:
nixsudo zypper install hapee-3.1r1-lb-adfspipnixsudo zypper install hapee-3.1r1-lb-adfspipnixsudo pkg install hapee-<VERSION>-lb-adfspipnixsudo pkg install hapee-<VERSION>-lb-adfspipExample for HAProxy Enterprise 3.1r1:
nixsudo pkg install hapee-3.1r1-lb-adfspipnixsudo pkg install hapee-3.1r1-lb-adfspip -
In the
global
section of your configuration, add directives that configure the module:hapee-lb.cfghaproxyglobalmodule-path /opt/hapee-3.1/modules/module-load hapee-lb-adfspip.soadfspip-load crt /etc/hapee-3.1/client.pem ca-file @system-ca jwt-verify-pubkey /etc/hapee-3.1/adfs-signing-pubkey.pemadfspip-register host adfs.example.com username user@example.com password P@ssword12345hapee-lb.cfghaproxyglobalmodule-path /opt/hapee-3.1/modules/module-load hapee-lb-adfspip.soadfspip-load crt /etc/hapee-3.1/client.pem ca-file @system-ca jwt-verify-pubkey /etc/hapee-3.1/adfs-signing-pubkey.pemadfspip-register host adfs.example.com username user@example.com password P@ssword12345where:
module-path
sets the file path to the enterprise modules folder.module-load
loads the ADFSPIP module.adfspip-load
sets the TLS certificates needed for establishing a trust relationship between the load balancer and the AD FS server. See Reference for details.adfspip-register
sets the host name of the AD FS server to connect to and the credentials of an Active Directory domain administrator that has access to that server. See Reference for details.
-
Unless your HAProxy Enterprise server can already resolve the hostname (for example,
adfs.example.com
), you’ll need to add aresolvers
section to your configuration to specify your DNS nameserver(s). For more information, see the topic DNS resolution.hapee-lb.cfghaproxyresolvers windows_server_dnsnameserver ns1 10.0.0.4:53hapee-lb.cfghaproxyresolvers windows_server_dnsnameserver ns1 10.0.0.4:53Then set the global directive
httpclient.resolver.id
to use it. This line should go before theadfspip-load
andadfspip-register
lines.hapee-lb.cfghaproxyglobalhttpclient.resolvers.id windows_server_dnsmodule-path /opt/hapee-3.1/modules/module-load hapee-lb-adfspip.soadfspip-load crt /etc/hapee-3.1/client.pem ca-file @system-ca jwt-verify-pubkey /etc/hapee-3.1/adfs-signing-pubkey.pemadfspip-register host adfs.example.com username user@example.com password P@ssword12345hapee-lb.cfghaproxyglobalhttpclient.resolvers.id windows_server_dnsmodule-path /opt/hapee-3.1/modules/module-load hapee-lb-adfspip.soadfspip-load crt /etc/hapee-3.1/client.pem ca-file @system-ca jwt-verify-pubkey /etc/hapee-3.1/adfs-signing-pubkey.pemadfspip-register host adfs.example.com username user@example.com password P@ssword12345 -
Save the file then reload the load balancer to apply the configuration changes:
nixsudo systemctl reload hapee-3.1-lbnixsudo systemctl reload hapee-3.1-lb -
Your load balancer access logs should show that the HAProxy Enterprise server is communicating with the AD FS server successfully. For example, check the log file
/var/log/hapee-3.1r1/lb-access-<DATE>.log
. The200
HTTP status indicates success.lb-access-DATE.logtext<MOD-ADFSPIP> -/- 4/0/22/152/176 200 340 - - ---- 0/0/0/0/0 0/0 {10.0.0.4}"POST https://adfs.example.com/adfs/proxy/EstablishTrust HTTP/1.1"<MOD-ADFSPIP> -/- 4/0/0/40/42 200 222 - - ---- 0/0/0/0/0 0/0 {10.0.0.4}"GET https://adfs.example.com/adfs/proxy/WebApplicationProxy/trust?api-version=1 HTTP/1.1"<MOD-ADFSPIP> -/- 3/0/0/58/59 200 6997 - - ---- 0/0/0/0/0 0/0 {10.0.0.4}"GET https://adfs.example.com/adfs/proxy/GetConfiguration?api-version=2 HTTP/1.1"<MOD-ADFSPIP> -/- 3/0/0/43/44 200 656 - - ---- 0/0/0/0/0 0/0 {10.0.0.4}"GET https://adfs.example.com/adfs/proxy/RelyingPartyTrusts?api-version=1 HTTP/1.1"lb-access-DATE.logtext<MOD-ADFSPIP> -/- 4/0/22/152/176 200 340 - - ---- 0/0/0/0/0 0/0 {10.0.0.4}"POST https://adfs.example.com/adfs/proxy/EstablishTrust HTTP/1.1"<MOD-ADFSPIP> -/- 4/0/0/40/42 200 222 - - ---- 0/0/0/0/0 0/0 {10.0.0.4}"GET https://adfs.example.com/adfs/proxy/WebApplicationProxy/trust?api-version=1 HTTP/1.1"<MOD-ADFSPIP> -/- 3/0/0/58/59 200 6997 - - ---- 0/0/0/0/0 0/0 {10.0.0.4}"GET https://adfs.example.com/adfs/proxy/GetConfiguration?api-version=2 HTTP/1.1"<MOD-ADFSPIP> -/- 3/0/0/43/44 200 656 - - ---- 0/0/0/0/0 0/0 {10.0.0.4}"GET https://adfs.example.com/adfs/proxy/RelyingPartyTrusts?api-version=1 HTTP/1.1"
4. Configure proxied applications Jump to heading
For each web application that you want to proxy traffic through HAProxy Enterprise you must publish it by adding a relying party trust.
On the AD FS server:
-
Create a Relying Party Trust:
- Open Server Manager and go to Tools > AD FS Management.
- Right click Relying Party Trust and select Add Relying Party Trust.
- In the Add Relying Party Trust Wizard dialog, select
Non claims aware
for the type of application. Click Start. - Set a display name, such as
webapp
, then click Next. - Set the relying party trust identifier, such as
https://webapp.example.com/
. It must use thehttps://
scheme and end with a trailing slash. click Add, then Next. The relying party trust identifier uniquely identifies the application for which you want to enable authentication. HAProxy Enterprise will relay traffic to this address inside the corporate network. - Set the access control policy. Select the Active Directory users and groups that should have access to this application. For example, you can select the Permit specific group option to set an active directory group that contains the users that should have access, such as
EXAMPLE\\OfficeWorkers
. Or choose Permit everyone. When finished, click Next. - Click Next on the Ready to Add Trust screen to complete the setup. Then Close.
On the HAProxy Enterprise server:
-
Add an
adfspip-register-server
directive to the global section:hapee-lb.cfghaproxyglobaladfspip-register-server url https://webapp.example.com/ external_url https://www.example.com/ backend webapp_backendhapee-lb.cfghaproxyglobaladfspip-register-server url https://webapp.example.com/ external_url https://www.example.com/ backend webapp_backendwhere:
url
matches the relying party trust identifier. It must use thehttps://
scheme and end in a trailing slash. HAProxy Enterprise will relay traffic to this address inside the corporate network.external_url
sets the URL at which external clients will access the application. It must use thehttps://
scheme. The relying party trust in AD FS will afterwards show this on its Proxy Endpoints tab.backend
sets the backend pool of servers to use.
-
Add a
frontend
section that receives traffic from clients. This frontend will accept requests for the external URL (for example,https://www.example.com
) and for the AD FS URL (for example,https://adfs.example.com
).hapee-lb.cfghaproxyfrontend webappbind :80bind :443 ssl crt /etc/hapee-3.1/wildcard.example.com.pemhttp-request redirect scheme https unless { ssl_fc }http-request add-header X-MS-Proxy haproxy-enterprisehttp-request adfspipuse_backend %[var(txn.adfspip.app_backend)] if { var(txn.adfspip.app_backend) -m found }default_backend adfs_serverhapee-lb.cfghaproxyfrontend webappbind :80bind :443 ssl crt /etc/hapee-3.1/wildcard.example.com.pemhttp-request redirect scheme https unless { ssl_fc }http-request add-header X-MS-Proxy haproxy-enterprisehttp-request adfspipuse_backend %[var(txn.adfspip.app_backend)] if { var(txn.adfspip.app_backend) -m found }default_backend adfs_serverwhere:
bind :443
receives HTTPS traffic. Note that in the example we’re using a wildcard certificate, but you could also setcrt
to a directory of certificates to have the load balancer choose the correct one based on SNI.http-request add-header
adds the requiredX-MS-Proxy
HTTP header, which indicates the name of the web proxy.http-request adfspip
checks the incoming request to route it to the sign-in page, validate clients with authentication tokens, and sets thetxn.adfspip.app_backend
variable to the value from theadfspip-register-server
directive’sbackend
argument.use_backend
relays requests to the correct web application backend based on thetxn.adfspip.app_backend
variable.default_backend
proxies sign-in requests to the AD FS federation server.
-
Add a backend for the web application and another for the AD FS server:
hapee-lb.cfghaproxybackend webapp_backendbalance roundrobinserver web1 10.0.0.10:443 ssl ca-file @system-ca checkbackend adfs_serverserver adfs adfs.example.com resolvers windows_server_dns ssl ca-file @system-ca sni str(adfs.example.com) crt /etc/hapee-3.1/client.pemhapee-lb.cfghaproxybackend webapp_backendbalance roundrobinserver web1 10.0.0.10:443 ssl ca-file @system-ca checkbackend adfs_serverserver adfs adfs.example.com resolvers windows_server_dns ssl ca-file @system-ca sni str(adfs.example.com) crt /etc/hapee-3.1/client.pemwhere:
- The backend named
webapp_backend
defines web application servers. That name of the backend, in this casewebapp_backend
, should match the value from theadfspip-register-server
directive’sbackend
argument. The servers must listen using HTTPS. - The backend named
adfs_server
defines the federation server(s). Itsserver
directive has aca-file
argument that validates the server’s TLS certificate. With a value of@system-ca
, it uses certificate authorities defined on the system, but you can also set it to a PEM file. Thesni
argument sets the SNI value to send to the federation server, without which the server won’t accept the request. Thecrt
argument sets the client certificate for authenticating the HAProxy Enterprise server to the federation server.
- The backend named
Reference Jump to heading
The ADFSPIP module supports the following global directives.
adfspip-load Jump to heading
Loads certificates for communicating with AD FS.
Syntax:
text
adfspip-load crt <cert> [ca-file <ca-file>] [ca-verify-file <ca-file>] jwt-verify-cert <jwt_cert>
text
adfspip-load crt <cert> [ca-file <ca-file>] [ca-verify-file <ca-file>] jwt-verify-cert <jwt_cert>
Argument | Description |
---|---|
crt |
PEM file containing the SSL client certificate that will be used for connections with the AD FS server. |
ca-file |
(optional) Designates a PEM file from which to load CA certificates used to verify server’s certificate. The @system-ca parameter could be used in place of the CA file in order to use the trusted CAs of your system, as done with the server directive. |
ca-verify-file |
(optional) Designates a PEM file from which to load CA certificates used to verify client’s certificate. The @system-ca parameter could be used in place of the CA file in order to use the trusted CAs of your system, as done with the server directive. |
jwt-verify-pubkey |
Public certificate used to verify the signature of JSON Web Tokens generated by the AD FS server. |
adfspip-register Jump to heading
Registers HAProxy Enterprise as a proxy with AD FS.
Syntax:
text
adfspip-register host <hostname> [username <admin-username>] [password <admin-password>]
text
adfspip-register host <hostname> [username <admin-username>] [password <admin-password>]
Argument | Description |
---|---|
host |
AD FS server hostname. |
username |
Username to be used to authenticate to the AD FS server. It can be set via the HAPROXY_ADFSPIP_USERNAME environment variable as well. If both are provided, the option from the configuration file will be taken first. |
password |
Password to be used to authenticate to the AD FS server. It can be set via the HAPROXY_ADFSPIP_PASSWORD environment variable as well. If both are provided, the option from the configuration file will be taken first. |
adfspip-register-server Jump to heading
Registers a web application with AD FS that will be proxied through HAProxy Enterprise.
Syntax:
text
adfspip-register-server url <url> backend <backend> [external_url <external_url>]
text
adfspip-register-server url <url> backend <backend> [external_url <external_url>]
Argument | Description |
---|---|
url |
Relying party trust internal URL. This is the address inside the corporate network that HAProxy Enterprise will relay requests to. |
external_url |
Corresponding external URL to the internal <url> . Clients outside the corporate network will use this URL to access the web application. |
backend |
Backend towards which end-user request must be forwarded. |
Troubleshooting Jump to heading
This section describes common troubleshooting steps.
General troubleshooting
Check the access log for errors, found in /var/log/hapee-3.1/lb-access-<date>.log
.
AD FS server returns 503 Service Unavailable
If you receive a 503
Service Unavailable response from the AD FS server, there are several possible causes:
-
In the
adfs_server
backend, check that theserver
line is setting an SNI value that matches the federation server’s service communications certificate. To view this certificate on the AD FS server:- Open Server Manager and go to Tools > AD FS Management.
- Expand Service and select Certificates.
- Right click the
Service communications
certificate and select View certificate.
-
On the AD FS server, check that the federation server’s name that you set when configuring AD FS matches the server’s hostname. If not, remove and reinstall the AD FS role.
-
Check that you set a relying party trust identifier that uses
https://
and ends with a trailing slash. -
Check that HAProxy Enterprise reports no errors when you run
sudo systemctl status hapee-3.1-lb
.
identifier not in the right format
If you receive the error message process_relyingpartytrust_resp: identifier not in the right format (not a uri)
, this could mean that the module is trying to parse relying party trusts that aren’t non-claims aware type applications. For example, you might have SAML applications registered in AD FS.
Do you have any suggestions on how we can improve the content of this page?