Skip to main content

How to integrate Active Directory Federation Services (ADFS) authentication with Red Hat SSO using SAML

Add Red Hat Single Sign-On (RHSSO) to ADFS to help improve user authentication and management.
How to set up terminal logging on Linux

Photo by Tatiana Syrikova from Pexels

Most businesses use Active Directory (AD) as it offers a single source of user management in the organization. Many organizations often incorporate additional authentication programs and protocols, such as Red Hat Single Sign On (RH-SSO), in tandem with AD. RH-SSO is based on Keycloak, an open source identity and access management tool for modern web applications.

This article demonstrates how to create the minimum necessary infrastructure to become familiar with and test RH-SSO. It also shows how to integrate it with Microsoft Active Directory Federation Services (ADFS) over the SAML protocol.

AD as an identity provider

ADFS is the web module that provides endpoints for using security tokens provided by either OpenID Connect (OIDC) or SAML Assertions with an AD server. ADFS is sometimes used as a bolt-on web server to AD on-premises, and it's common to find that an organization is running an old version. Nowadays, it's more common to use the Azure version of ADFS, which is more opinionated and perhaps easier to work with.

Because each AD system administrator has a different view on how to structure their AD database, providing one-size-fits-all guidance isn't practical. Instead, this article offers some pointers around the basic steps to set up integrations with ADFS.

[ Download now: 6 ways to promote organization-wide IT automation. ]

Integration workflow

The Unified Modeling Language (UML) diagram below shows a high level of the authentication steps used in this tutorial for using ADFS as an authentication provider for RH-SSO using the SAML protocol. To be clear, this is just one example of identity brokering. SAML is highly flexible, as is RH-SSO.

Image of a unified modeling language diagram
(James Force & Martin Sumner, CC BY-SA 4.0)

Here's the workflow:

  1. The user clicks the SAML button on the RH-SSO form.
  2. This sends a redirect to the browser, along with a SAML request for Auth.
  3. The browser sends an HTTP GET to the ADFS server passing the parameters for the Auth.
  4. ADFS returns a login form requesting the user log in.
  5. The user completes the login form and submits it, then HTTP POSTs the credentials back to the ADFS server.
  6. ADFS checks the credentials. Assuming they're legitimate, ADFS posts a SAML response with the mapped claims to the RH-SSO server. (The endpoint contacted is configured during setup using metadata exported from RH-SSO.)
  7. Upon receipt of the SAMLresponse, RH-SSO allows users to update their details. Upon submission, the credentials are added to RH-SSO’s user database.


The following is a simple architectural example of how you can configure and integrate ADFS and SSO.

Image of how to configure and integrate ADFS and SSO
( (James Force & Martin Sumner, CC BY-SA 4.0)

The diagram illustrates the basic topology for services that are aware of each other through exchanging metadata files:

  • FederationMetadata.xml contains information about your federation service for creating trusts, identifying token-signing certificates, and so on. It must be publicly available so that other parties can access and consume it. This file is generated first.
  • IdentityProviderMetadata.xml is the metadata produced and downloaded from Red Hat SSO. It contains the SAML service provider entity descriptor you can use to import into ADFS. This file is generated second.

Infrastructure architecture

To minimize the ADFS infrastructure footprint for this lab environment build, we've opted to provision a Windows Server 2016 VM, acting as the full Windows estate, and a Red Hat Enterprise Linux (RHEL) 8 virtual machine (VM), which runs SSO. In a more realistic scenario, the domain controller (DC), ADFS federation server, and Internet Information Services (IIS) web server would be split and made highly available.

  • Domain controller
    • Role: DC, DNS
    • Host: ad01
    • Operating system (OS): Win Server 2016
  • Federation server
    • Role: ADFS
    • Host: ad01
    • OS: Win Server 2016
  • WebServer
    • Role: IIS
    • Host: ad01
    • OS: Win Server 2016
  • RH-SSO
    • Role: JBoss
    • Host: sso01
    • OS: RHEL 8

Getting started

By the end of this tutorial, you will configure:

  • Windows Server 2016 server with the following roles: DC, ADFS, IIS
  • RHEL server running RH-SSO
  • Trust between SSO and ADFS
  • User authentication against AD via SSO

This setup uses the command-line interface (CLI) as much as possible: PowerShell for Windows hosts and Bash for Linux hosts. We're presenting these tasks to help make the manual steps involved in the process clear. In the real world, you would use automation to reduce deployment and configuration time and increase consistency, repeatability, and reliability.

[ Download now: A system administrator's guide to IT automation. ]

This article assumes that the machines are on the same network and can communicate with each other freely.

To work through these examples, you need:

  • RHEL 8 installation media or virtual machine (VM) templates
  • Microsoft Windows Server 2016 installation media or VM templates and associated licenses
  • Credentials for Red Hat Subscription Manager (RHSM)
  • RH-SSO installation media

1. Configure the domain controller

This example models a single organization, named Example ( The following PowerShell command installs the AD DS Windows feature and its dependencies, invokes the deployment module, then configures the target system as an AD DC (and configures DNS for the domain):

PS> Rename-Computer -NewName ad01PS> Get-windowsfeature
PS> Install-WindowsFeature -name NET-Framework-Core  
PS> Install-windowsfeature -name AD-Domain-Services -IncludeManagementTools  

PS> Import-Module ADDSDeployment
PS> Install-ADDSForest `
-CreateDnsDelegation:$false `
-DatabasePath "C:\Windows\NTDS" `
-DomainMode "WinThreshold" `
-DomainName "" `
-DomainNetbiosName "example" `
-ForestMode "WinThreshold" `
-InstallDns:$true `
-LogPath "C:\Windows\NTDS" `
-NoRebootOnCompletion:$false `
-SysvolPath "C:\Windows\SYSVOL" `
-Force:$true `
-SafeModeAdministratorPassword (ConvertTo-SecureString –String 'Pa33w0rd!' -AsPlainText -Force)

Validate the configuration:

PS> Get-Service adws,kdc,netlogon,dns
PS> Get-SmbShare
PS> dcdiag /q
PS> Resolve-DnsName
PS> Resolve-DnsName

1a. Configure users and groups

You can use AD security groups to group domain users with similar roles, departments, or organizational responsibilities or to reflect other organizational concerns. This allows you to assign permissions at the group level, reducing the management overhead as users join, change roles or departments, or leave. The following PowerShell example creates domain security groups and domain users and assigns those users to the groups.

[ Download now: A sysadmin's guide to Bash scripting. ]

First, create directories:

PS> New-ADGroup -Name "Officers" -SamAccountName Officers -GroupCategory Security -GroupScope Global -DisplayName "Bridge Officers" -Path "CN=Users,DC=example,DC=Com" -Description "Members of Bridge Officers"

PS> New-ADGroup -Name "Engineers" -SamAccountName Engineers -GroupCategory Security -GroupScope Global -DisplayName "Engineering Crew" -Path "CN=Users,DC=example,DC=Com" -Description "Members of Engineering Crew"

Then create your users:

PS> $Attributes = @{
   Enabled = $true
   ChangePasswordAtLogon = $false
   UserPrincipalName = ""
   Name = "dallas"
   GivenName = "Captain"
   Surname = "Dallas"
   DisplayName = "Captain Dallas"
   Office = "Bridge"
   AccountPassword = "Thatfigures." | ConvertTo-SecureString -AsPlainText -Force 

PS> New-ADUser @Attributes
PS> $Attributes = @{
   Enabled = $true
   ChangePasswordAtLogon = $false
   UserPrincipalName = ""
   Name = "kane"
   GivenName = "XO"
   Surname = "Kane"
   DisplayName = "XO Kane"
   Office = "Bridge"
   AccountPassword = "Sillyquestion?" | ConvertTo-SecureString -AsPlainText -Force

PS> New-ADUser @Attributes
PS> $Attributes = @{
   Enabled = $true
   ChangePasswordAtLogon = $false
   UserPrincipalName = ""
   Name = "parker"
   GivenName = "Chief"
   Surname = "Parker"
   DisplayName = "Chief Parker"
   Office = "Engineering"
   AccountPassword = "Howyadoin?" | ConvertTo-SecureString -AsPlainText -Force

PS> New-ADUser @Attributes
PS> New-ADUser -Name "John Smith" -GivenName "John" -Surname "Smith" -SamAccountName "jsmith" -UserPrincipalName "" -Path "CN=Users,DC=example,DC=Com" -AccountPassword(Read-Host -AsSecureString "Input Password") -Enabled $true

Add users to security groups:

PS> Add-ADGroupMember -Identity Officers -Members dallas, kane
PS> Add-ADGroupMember -Identity Engineers -Members parker

And validate that the users exist:

PS> net user kane
PS> net user parker
PS> net user dallas

1b. Create a Group Managed Service Account (GMSA)

This account can also be used during the Install-AdfsFarm process instead of giving admin credentials:

Add-KdsRootKey -EffectiveTime (Get-Date).AddHours(-10) 
New-ADServiceAccount FsGmsa -DNSHostName -ServicePrincipalNames http/

2. Configure the federation server (ADFS)

The following PowerShell command installs ADFS and its dependencies, then invokes the deployment module, and sets up a certificate. For ease of use, this lab environment creates a wildcard certificate (rather than the suggested method of creating specific common names):

PS> Install-windowsfeature adfs-federation –IncludeManagementTools
PS> Import-Module ADFS

PS> add-windowsfeature adcs-cert-authority -IncludeManagementTools
PS> Install-AdcsCertificationAuthority -CAType EnterpriseRootCa
PS> Install-PackageProvider nuget -force
PS> Install-Module -Name PSPKI -Force
PS> Import-Module -Name PSPKI

PS> New-SelfSignedCertificate -certstorelocation cert:\localmachine\Root -dnsname *
PS> Get-ChildItem -path cert:\LocalMachine\My

When running the next set of PowerShell commands, you get a credentials prompt. The format is domain\user (for example,\Administrator). Replace the hashes with the cert thumbprint for the wildcard cert, which can be viewed using the Get-ChildItem command:

PS> $fscredential = Get-Credential
PS> Get-ChildItem -path cert:\LocalMachine\My

PS> Install-AdfsFarm -CertificateThumbprint ################################ -FederationServiceName -ServiceAccountCredential $fscredential

PS> Install-AdfsFarm -CertificateThumbprint ################################ -FederationServiceName -ServiceAccountCredential $fscredential -OverwriteConfiguration

PS> Set-AdfsProperties -EnableIdPInitiatedSignonPage $true

Should you encounter an error and need to rerun this, use the -OverwriteConfiguration flag.

[ Want to test your sysadmin skills? Take a skills assessment today. ]

To configure Active Directory's Device Registration Service (DRS), enter the domain and GMSA account you set up earlier:

PS> Initialize-ADDeviceRegistration\fsgmsa$
PS> Enable-AdfsDeviceRegistration                               
PS> Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationEnabled $true

Add the required DNS records associated with your environment:

PS> Get-DnsServerResourceRecord -ZoneName

PS> Add-DnsServerResourceRecordA -Name ad01 -ZoneName -IPv4Address ###.###.##.###
PS> Get-DnsServerResourceRecord -ZoneName -RRType A

PS> Add-DnsServerResourceRecordCName -ZoneName -HostNameAlias "" -Name "enterpriseregistration"
PS> Get-DnsServerResourceRecord -ZoneName -RRType CName

3. Configure the web server (IIS)

Install the IIS feature and its dependencies, as well as the .NET framework:

PS> Install-WindowsFeature Web-Server -IncludeManagementTools -IncludeAllSubFeature -ComputerName ad01 -WhatIf
PS> Install-WindowsFeature Windows-Identity-Foundation -IncludeManagementTools
PS> Install-WindowsFeature Net-Framework-Core

The web address validates as long as ADFS is working:

PS> Start-Process ""
PS> Start-Process ""
PS> Start-Process ""

4. Install and configure RH-SSO

On your Linux server, install Java 8, unpack SSO into a relevant directory, and set up an administrator user, named sysadmin:

$ sudo dnf install java-1.8.0-openjdk
$ unzip -d /opt
$ chmod -R 770 /opt/rh-sso-7.3
$ cd /opt/rh-sso-7.3/bin
$ sh ./ -u sysadmin

For the sake of this exercise, amend standalone.xml to bind to all available addresses:

$ cd /opt/rh-sso-7.3/standalone/configuration
$ sed -i 's/' standalone.xml
$ sh ./

You'll see a login screen for SSO at Using WebConsole, create a realm named demo. If you need assistance with this, follow the SSO getting started guide.

4a. Set up SSL

Verify connectivity to the ADFS server, export the certificate, and then import that server's certificate into a system trust store:

$ cd /opt/rh-sso-7.3
$ wget
$ openssl s_client -connect 2>/dev/null </dev/null |  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' >> ad01.cer
$ cp ad01.cer /usr/share/pki/ca-trust-source/anchors/
$ update-ca-trust
$ trust list
$ wget

4b. Configure outgoing HTTP requests

Create a Java trust store for JBoss, and then import the ADFS server certificate into it:

$ cd /opt/rh-sso-7.3
$ keytool -import -alias -keystore truststore.jks -file ad01.cer

Add the block below for the trust-store configuration to the standalone.xml configuration file (near the bottom under the spi sections):

<spi name="truststore">
     <provider name="file" enabled="true">
             <property name="file" value="/opt/rh-sso-7.3/truststore.jks"/>
             <property name="password" value="test77"/>
             <property name="hostname-verification-policy" value="ANY"/>
             <property name="disabled" value="false"/>

After amending standalone.xml, restart JBoss to pick up the changes.

[ Download now: Advanced Linux commands cheat sheet. ]

4c. Enable inbound SSL/HTTPS for the Keycloak server

Keycloak is an open source identity and access management tool. To enable SSL (and HTTPS) for the Keycloak server, first create a Java trust store with a self-signed certificate:

$ cd /opt/rh-sso-7.3
$ keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950
Enter keystore password:  test77
Re-enter new password: test77
$ keytool -importkeystore -srckeystore keycloak.jks -destkeystore keycloak.jks -deststoretype pkcs12
$ ./bin/ config truststore --trustpass test77 /opt/rh-sso-7.3/keycloak.jks
$ cp keycloak.jks standalone/configuration

In the JBoss CLI, add the key-store information, and enable extra logging:

$ cd /opt/rh-sso-7.3/bin
$ ./


/core-service=management/security-realm=UndertowRealm/server-identity=ssl:add(keystore-path=keycloak.jks, keystore-relative-to=jboss.server.config.dir, keystore-password=test77)

/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=security-realm, value=UndertowRealm)




5. Integrate SSO with ADFS

You can integrate SSO with ADFS in the RH-SSO web user interface (UI). Here's the overview of the process:

  1. Click Add Provider (SAML v2) to configure an identity provider.
  2. At the bottom of the page, select Import from URL and enter the ADFS server federation metadata URL (for example:
  3. Set NameID Policy Format to email.
  4. Click Save.
Image of how to add identity provider
 (James Force & Martin Sumner, CC BY-SA 4.0)

Export the SAML endpoint metadata from the Web UI or by accessing the endpoint https://<Hostname>:<PORT>/auth/realms/<Realm>/broker/<IdentityProvider>/endpoint/descriptor.

Image of identity providers
 (James Force & Martin Sumner, CC BY-SA 4.0)

6. Integrate ADFS with SSO

The next step involves adding relying party trusts. Import the metadata for the SSO server's configuration details from the metadata XML file you previously downloaded or directly from the URL:

PS> Add-AdfsRelyingPartyTrust -Name "SSO" -MetadataFile "c:\metadatafile.xml" -AccessControlPolicyName "Permit Everyone"

Specify the metadata XML file, as it allows the XML file to be modified in cases such as when the output is HTTP endpoints and not HTTPS. 

From a URL:

PS> Add-AdfsRelyingPartyTrust -Name "SSO" -MetadataURL "https://<HOST>:<PORT>/auth/realms/<REALM_NAME>/broker/saml/endpoint/descriptor" -AccessControlPolicyName "Permit Everyone"

Provide the URL for SSO's metadata, as mentioned above: 


6a. Add relying party trusts mapping rules

Then add relying party trust mapping rules. To add the rules, create the file C:\rules.txt with the following contents:

@RuleTemplate = "MapClaims"
@RuleName = "Name ID"
c:[Type == ""]
 => issue(Type = "", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties[""] = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");

@RuleTemplate = "LdapClaims"
@RuleName = "Email, subject"
c:[Type == "", Issuer == "AD AUTHORITY"]
 => issue(store = "Active Directory", types = ("", ""), query = ";mail,sAMAccountName;{0}", param = c.Value);

Then run this PowerShell command to add the rules:

PS> Set-AdfsRelyingPartyTrust -TargetName "Destination Relying Party Trust" -IssuanceTransformRulesFile "C:\rules.txt"

If you want to add additional rules with the ADFS Management graphical user interface (GUI), re-export the rules to text with:

PS> (Get-AdfsRelyingPartyTrust -Name "saml").IssuanceTransformRules | Out-File "C:\rules.txt"

6b. Add rules with a GUI (optional)

The following is not needed if you run the previous PowerShell. However, it illustrates how to add relying party trust rules for mapping, which is easier to do via the GUI initially if you are unsure about the exact mapping configuration.

The two examples below show how to do the previous configuration for mapping user ID and user attributes. 

Rules for mapping user IDs (GUI)
  1. In the Windows server configuration GUI, navigate to Relying Party Trusts and select the new item. Then, in the right-side Actions bar, select Edit Claim Issuance Policy.
  2. Select Add Rule.
  3. For the Claim rule template, select Transform an incoming claim.
  4. Map the following attributes:
    1. Claim rule name: Name ID
    2. Incoming claim type: Windows account name
    3. Outgoing claim type: Name ID
    4. Outgoing name ID format: Email
  5. Click Finish to add the rule.
Rules for mapping standard user attributes (GUI)
  1. In the Windows server GUI, navigate to Relying Party Trusts and select the new item. Then, in the Actions bar, select Edit Claim Issuance Policy.
  2. Select Add Rule.
  3. For the Claim rule template, select Send LDAP attributes as Claims.
  4. Map the following attributes:
    1. E-Mail-Addresses: Email address
    2. SAM-Account-Name: Subject name
  5. Add other attributes, if needed, such as your LDAP attributes for surname and given name.
  6. Click Finish to commit the rules.

7. Test and validate

In a web browser, open your SSO login page for the realm you set up by navigating to https://<SSO_HOST>:<PORT>/auth/realms/<REALM>/account.

Click saml to go to your organization's page (ADFS).

Image of a login demo
 (James Force & Martin Sumner, CC BY-SA 4.0)

Log on with an example user's AD credentials to validate that AD domain users can authenticate against SSO with their domain credentials.

Login screen for AD credentials

You're logged in and redirected to SSO, where you now see your account details.

Account details
(James Force & Martin Sumner, CC BY-SA 4.0)

Once you've successfully logged on, you see a response in the JBoss server logs, which are stored at $JBOSS_HOME/standalone/logs/server.log:

<?xml version="1.0" encoding="UTF-8"?>samlp:Response ID="_b37dfe49-822b-46ec-8919-869ebfa63b2d" Version="2.0" IssueInstant="2020-02-20T12:26:54.794Z" Destination="" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="ID_dd02e34f-40b2-4a2a-b972-87be50a8a9a7" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion"></Issuer>
  <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
    <KeyInfo xmlns="">
    <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">example\Administrator</NameID>
    <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
      <SubjectConfirmationData InResponseTo="ID_dd02e34f-40b2-4a2a-b972-87be50a8a9a7" NotOnOrAfter="2020-02-20T12:31:54.801Z" Recipient="" />
  <Conditions NotBefore="2020-02-20T12:26:54.755Z" NotOnOrAfter="2020-02-20T13:26:54.755Z">
    <Attribute Name="">
  <AuthnStatement AuthnInstant="2020-02-20T12:26:54.643Z" SessionIndex="_8f000dc3-31cf-48c0-80d9-bcccaa409e2e">

If you don't see these messages, make sure that debug logs are active:

$JBOSS_HOME/bin/ --connect

Integrated authentication

Congratulations. You have set up SSO integration with ADFS successfully! Red Hat's SSO technology is for the whole of your network, and it has the integration to enable it. Use RH-SSO to make your login process unified and universal.

Author’s photo

James Force

James Force is a Senior Consultant at Red Hat. After working in a handful of infrastructure engineering and consulting jobs, James joined Red Hat at the start of 2020. More about me

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.