Tag Archives: ADFS

Backup and Recovery with the AD FS Rapid Restore Tool

Slipping out of the Microsoft stable recently with little fanfare, the AD FS Rapid Restore Tool. As the name suggests, this is a tool geared at aiding in the recovery of your AD FS configuration / environment, in the event of server failure or disaster. To date, effectively backing key material and/or relying parties has been a proverbial thorn-in-the-side for AD FS administrators, so the release of this utility is very interesting.

Does this tool do the trick? Let’s give it a whirl…

Download the MSI and install the tool.  You can get the MSI from here. Supported versions are AD FS 2012 R2 and AD FS 2016. The tool is directly installed on the farm node and the installation process is very straightforward ( a la Next Next Next).


With the tool installed we can launch a Administrative PowerShell prompt and then import the module.


Let’s look at some of the command option via Get-Help Backup-ADFS -full


As can be seen from the graphic above, when we call the Backup-ADFS cmdlet, backup of the AD FS configuration is possible to both the filesystem or to Azure. In these test scenarios, the local file system is used.

A backup folder (e.g. C:\ADFSExport) is created manually as the backup/restore location. The Backup-ADFS cmdlet is then run. Here’s the syntax used for testing.

Backup-ADFS -StorageType “FileSystem” -StoragePath “C:\ADFSExport\” -EncryptionPassword “12345678” -BackupComment “Clean Install of ADFS (FS)” -BackupDKM


Oops.. a warning. As the Microsoft documentation points out, your AD FS SSL/TLS certificate will only be backed up during the export if the private keys are marked as exportable and the associated Manage Private Keys permission is given to the user running the script. In the above example, my certificate does not fit that criteria. A simple way to check beforehand is to attempt to export the SSL certificate via the Certificate Export Wizard.  If “Yes, export the private key” is greyed out, it’s not exportable. Now go find that PFX ……


Where the script can’t handle the service communication certificate migration, the PFX should be manually imported on the replacement server before the restore script is run.

By the way, the token signing and decryption certificates (incl. private keys) used by AD FS are stored in the AD FS configuration database itself. These certificates are then encrypted using something called the Distributed Key Manager (DKM). A container is created in the local Active Directory  of your AD FS during installation of the first AD FS node in the farm. The DKM master key is then stored in this container. The recovery tool provides for backup of the DKM facility and in the export command-line above the “Backup-DKM” is used. I’m no expert on DKM, so if you require a more detailed information, I suggest you go hunting here.

Onto the recovery. Here I wanted to test a number of changes.

Same Server Recovery

For this simple test, we elected to remove the AD FS farm (primary) role  in each case and cleaned out the AD FS container in Active Directory (CN=ADFS,CN=Microsoft,CN=Program Data). A fresh installation of AD FS was then made, the tool installed and then the restore operation begun.  Any existing configuration database was overwritten.

Restore 1 – Basic

To begin with, in the first restore, we help the tool along a little bit by partially rebuilding the AD FS server. I added the AD FS role manually via Server Manager, specified the federation service name, the SSL certificate to use and the relevant service account. Here the recovery script was as follows:

Restore-ADFS -StorageType “FileSystem” -StoragePath “C:\ADFSExport\” -DecryptionPassword “12345678” -RestoreDKM

Restore worked fine. No errors and the WAP connected back to the “new” farm without issues.

Restore 2 – Complete

This option required providing the command-line with a little more information as the role was not pre-installed. Consequently, those missing elements, pre-loading of SSL/TLS service communications certificate aside, needed specifying.

Restore-ADFS -StorageType “FileSystem” -StoragePath “C:\ADFSExport\” -DecryptionPassword “12345678” -RestoreDKM -ADFSName “adfs.mydomain.com” -DBConnectionString “WID” -GroupServiceAccountIdentifier “MYDOMAIN\gmadfs$”

Again, no issues. Impressive.

That SSL error during the initial export was still bugging me though. Just to make sure that SSL export really was supported, I flipped the Service Communications certificate in AD FS to one with an exportable private key (the replacement certificate was one from a local test CA, complete with Server Authentication EKU). The cert then needed to be assigned to AD FS  via PowerShell.

dir cert:\LocalMachine\My
Set-AdfsCertificate -CertificateType Service-Communications -Thumbprint thumbprint
Set-AdfsSslCertificate -Thumbprint thumbprint


After an AD FS  restart, with the new certificate in place, I then reran a new export:


As can be seen from the above screenshot, with the exportable cert in place there were no SSL errors this time. Removing AD FS and then rerunning the Restore-ADFS cmdlet an additional  time then demonstrated that the SSL certificate was then imported as part of the recovery.  Nice.

New Server Recovery

Of course, no test is worth its weight in custard unless we actually go the extra mile and try and break stuff.  In the next scenarios, we’ll tweak the configuration a little, moving AD FS to a completely new server and do a database recovery to a new format.

Restore 1 – WID to SQL

As well as introducing a new server, complete with different IP, computer name etc., we will also migrate the recovered solution to a new database form factor, as part of the recovery. Via the script, the original Windows Internal Database (WID)-based AD FS solution will be refactored in SQL Server.

Restore-ADFS -StorageType “FileSystem” -StoragePath “C:\ADFSExport\” -DecryptionPassword “12345678” -RestoreDKM -ADFSName “fed.route443.net” -DBConnectionString “data source=sqlserverFQDN;initial catalog=adfsconfiguration;integrated security=true” -GroupServiceAccountIdentifier “MYDOMAIN\gmadfs”

The change in the script is minimal from previous cases. In order to effect the transition from WID to SQL we simply provide the necessary connection string in the Restore-ADFS cmdlet so that the recovery tool can provision the AD FS configuration and Artifact database on the SQL Server. Running the restore script against Backup ID 8 (in this example).


The restore is complete without errors. On the SQL Server in Management Studio, the databases are successfully provisioned.


On our Web Application Proxy (WAP) in a HOSTS file (or DNS – YMMV), we update the reference to the AD FS farm pointing to the new IP address. Excellent! Cue login test page and successful logon.


Restore 2 – SQL to WID

Believe it or not, the request to move from SQL to Windows Internal Database (WID) does come up from time-to-time on Technet forums, so I thought I’d validate this scenario also. Here we’re moving back our AD FS configuration database(s) running on a SQL workload to WID. We back up our ADFS/SQL server  and then copy the C:\ADFSExport folder to the newly minted server. Here the following syntax is then run:

Restore-ADFS -StorageType “FileSystem” -StoragePath “C:\ADFSExport” -DecryptionPassword “12345678” -RestoreDKM -ADFSName “adfs.mydomain.com” -DBConnectionString “WID” -GroupServiceAccountIdentifier “MYDOMAIN\gmadfs$”


Item 9 is the ADFS/SQL backup which we wish to restore. Again, on the WAP we point away from our old ADFS / SQL pair to our freshly restored ADFS / WID combination and test logon and we’re up and running.


This is an outstanding tool and one every AD FS administrator should be in possession of. Not to be underestimated, the AD FS Rapid Restore tool not only  adds great value to the recovery process, but also provides an excellent means for copying/mirroring your environment AD FS for testing. Moreover, as can be seen from the previous screenshots, it’s also an excellent way of backing up and charting your AD FS configurations vis-a-vis change management.

AD FS – Old Habits (idpinitiatedsignon.aspx)

Usually after building an AD FS/WAP farm I test locally from the Internet and the Intranet using (to-date) a fairly reliable source of verification that the service is up and running. I’m referring to, of course, the IdP sign-in page (../adfs/ls/idpinitiatedsignon.aspx). This offers a simple way of validating login via AD FS.

With Windows Server 2016, this page is no longer surfaced “out-of-the-box”.. if you want to do a SAML 2.0  IdP-initiated sign-on, this functionality will need to be enabled. Otherwise, connecting to the obligatory sign-in page, will produce an error similar to the following:


Testing from the Web Application Proxy itself directly,  pointing to the AD FS farm, we may see an HTTP 503 Service Not Available error.

Via Powershell, it can be switched back on:

set-adfsproperties -EnableIdpInitiatedSignon $True

Now, before we get too hasty,  knowing that we can turn it back on versus actually turning it back on are two different things 🙂 If it’s directly required, IdP-driven sign-on is a feature of your federation setup, then you may have no choice. For example, certain SaaS/Cloud applications simply don’t support SP-initiated workflow.

For some organizations I’ve worked for though, this page is seen as insidious because it reveals the relying parties configured on your AD FS farm anonymously.

AD FS 2.0


AD FS 2012 R2


Going back to AD FS 2.0, customers are often unwilling to float this data anonymously via the sign-in page and want to hide the RP enabled trusts visible on the page, sometimes re-writing the code behind to do so or even hiding it from the browser via obfuscation.

Whatever your view, it’s off by default in Windows Server 2016. Those of a paranoid bent may now breathe …………. in….. out….in… out…. there you go 🙂



Interoperability scenarios with simpleSAMLphp and AD FS


Hello all and Happy New Year!

In this post we’ll look at inter-operability scenarios involving simpleSAMLphp and Active Directory Federation Services (AD FS).

simpleSAMLphp is a native PHP application that provides support for a number of authentication protocols/methods. Its origins lie with the SAML protocol, but it also provides support for a range of other authentication protocols (e.g. WS-Federation, OAuth, LDAP, RADIUS).  It’s a very capable and robust platform that can run on a number of different web surfaces.

In this post we’ll be covering identity federation scenarios with simpleSAMLphp and our usual incumbent: AD FS, getting the two to play nicely together.  We’ll look at both sides of the coin via a:

(a)    simpleSAMLphp Service Provider (SP) / AD FS Identity Provider (IdP) pairing.

(b)   simpleSAMLphp Identity Provider (IdP) / AD FS Service Provider (SP) pairing;


In both cases, setup is applicable to both AD FS 2.0 and AD FS 3.0/2012 R2.

For an introduction to simpleSAMLphp, start here.  It runs on a wide variety of web servers (Apache, Nginx, IIS among others).  In these scenarios we’ll use IIS as our web server for deployment.


The latest PHP libraries can be obtained through the IIS Web Platform Installer. In this setup PHP 5.5.x is used and simpleSAMLphp 1.13.x.

The latest binaries for simpleSAMLphp are available via their website (http://www.simplesamlphp.org).

For SAML integration with AD FS, SSL certificate(s) are required to secure the IIS website(s) and the underlying simpleSAMLphp application(s). This pre-requisite stems from AD FS supporting HTTPS only.  In the test configuration described here, the simpleSAMLphp instances are also published behind an AD FS Web Application Proxy (WAP). The pass-through (reverse) proxy functions of the WAP are then used to publish the simpleSAMLphp IdP/SP endpoints.  On the IIS side, Server Name Indication (SNI) is also enabled. 

The test setup used here comprises four virtual machines:

(i)                  An Active Directory Domain Services (AD DS) and Certificate Services (AD CS) node;

(ii)                An Active Directory Federation Services (AD FS) 2012 R2 Farm node;

(iii)               A Web Application Proxy (WAP) 2012 R2 node;

(iv)              An IIS 8.5 Web server with php loaded as an application. This hosts the simpleSAMLphp Identity Provider (IdP), Service Provider and test applications, under dedicated websites/paths.


The AD DS and AD CS instances provide authentication and the SSL certificates for the IIS web services. On the Web Application Proxy (WAP) a third-party certificate is installed. This goes somewhat against the grain with Microsoft recommendations of using the same certificate pairing on the WAP and AD FS. However, since we’re not using device management/Workplace Join in this scenario, which I believe the requirements stem from, there are no immediate issues.

On our “application server” IIS is installed. Herein, I’ve created four websites (idp1, idp2, site1 and site2), representing two simpleSAMLphp SAML 2.0 identity providers and two simpleSAMLphp service providers. The website configuration can be seen in the below graphic:


In each case the simpleSAMLphp files are unzipped to a folder per function, e.g:

·         c:\inetpub\idp1 and c:\inetpub\idp2 for the SAML identity provider (IdP) root paths

·         c:\inetpub\web1 and c:\inetpub\web2 for the SAML server provider (SP) root paths

In IIS Manager, we can see the folder structure of an exploded simpleSAMLphp configuration for a single instance.


In each instance, under the config folder, a baseurlpath setting in the config.php file is set to indicate the root path for simpleSAMLphp content. By default, this is set to www.  Should we wish to change this, such that the desired path to our simpleSAMLphp is say https://idp1.mydomain.com/auth  rather than the default https://idp1.mydomain.com/www, then we make the change to the baseurlpath from ‘www/’ to auth/ and rename the www folder accordingly. Note the use of the trailing slash that should always be present in the  baseurlpath value.

From a simpleSAMLphp standpoint, there’s a few tweaking steps required before we get going in our test setup.

By default, a secretsalt setting is configured in the config.php file and it’s strongly recommended to change this. This should be a random string, as the salt is used to generate cryptographically secure hashes.

Also, we should consider getting logging working properly. This will reap dividends later when it comes to troubleshooting. As with other settings so far mentioned, logging settings are defined in config.php.

Firstly, debug is enabled via setting:                               

‘debug’ => TRUE,

By default, the logging level is set to SYSLOG.  Here we’ll also switch the logging level to DEBUG and then alter the handler to file. This is done by setting the following values:

     ‘logging.level’         => SimpleSAML_Logger::DEBUG,

       ‘logging.handler’       => ‘file’,


In later sections of the CONFIG.PHP file, the output filename is also specified. This writes to the log folder of the instance.

‘logging.logfile’          => ‘simpleSAMLphp.log’,

This log file lives under the /log folder of the simpleSAMLphp instance. However, simply specifying the file to use is not sufficient for logging under IIS to work.   For that little feat, the IUSR needs to been given modify access to the simpleSAMLphp logfile.


Repeat this process for each instance of simpleSAMLphp running under IIS on your server(s), giving the IUSR account the appropriate permissions.

Once logging has been configured, we can see the benefits of verbose logging as it provides a rich level of detail. Here’s a sample:


Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       <Attribute xmlns:a=”http://schemas.xmlsoap.org/ws/2009/09/identity/claims&#8221; Name=”http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-ip&#8221; a:OriginalIssuer=”CLIENT CONTEXT”>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]         <AttributeValue>172.16.x.6</AttributeValue>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       </Attribute>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       <Attribute xmlns:a=”http://schemas.xmlsoap.org/ws/2009/09/identity/claims&#8221; Name=”http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-forwarded-client-ip&#8221; a:OriginalIssuer=”CLIENT CONTEXT”>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]         <AttributeValue>212.x.y.5</AttributeValue>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       </Attribute>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       <Attribute xmlns:a=”http://schemas.xmlsoap.org/ws/2009/09/identity/claims&#8221; Name=”http://schemas.microsoft.com/ws/2012/01/insidecorporatenetwork&#8221; a:OriginalIssuer=”CLIENT CONTEXT”>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]         <AttributeValue xmlns:tn=”http://www.w3.org/2001/XMLSchema&#8221; xmlns:b=”http://www.w3.org/2001/XMLSchema-instance&#8221; b:type=”tn:boolean”>false</AttributeValue>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       </Attribute>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       <Attribute xmlns:a=”http://schemas.xmlsoap.org/ws/2009/09/identity/claims&#8221; Name=”http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-endpoint-absolute-path&#8221; a:OriginalIssuer=”CLIENT CONTEXT”>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]         <AttributeValue>/adfs/ls/</AttributeValue>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       </Attribute>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       <Attribute xmlns:a=”http://schemas.xmlsoap.org/ws/2009/09/identity/claims&#8221; Name=”http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent&#8221; a:OriginalIssuer=”CLIENT CONTEXT”>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]         <AttributeValue>Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; WOW64; Trident/7.0; Touch; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; Tablet PC 2.0; InfoPath.3; MASEJS)</AttributeValue>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       </Attribute>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       <Attribute xmlns:a=”http://schemas.xmlsoap.org/ws/2009/09/identity/claims&#8221; Name=”uid” NameFormat=”urn:oasis:names:tc:SAML:2.0:attrname-format:basic” a:OriginalIssuer=”https://idp1.mylos.net/www/saml2/idp/metadata.php”&gt;

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]         <AttributeValue>student</AttributeValue>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]       </Attribute>

Sep 19 17:30:19 simpleSAMLphp DEBUG [5805446797]     </AttributeStatement>


Back in IIS, I’ve elected to employ the services of our friend Server Name Indication (SNI). This is defined on the website. Unlike with AD FS, SNI is an option under IIS J



SNI allows us to run multiple web sites under IIS, using different certificates/domain combinations per website, all bound to a shared single IP address. This makes it possible in this test setup to run with numerous instances of simpleSAMLphp, in identity and service provider roles, all on the same server; without having to deal with the hassle of SSL Host Headers, listener changes, tweaking friendly names on certificates etc.

Web server setup itself is pretty straightforward. For simpleSAMLphp instances, either identity or service provider, we prep the web server with the following steps:

    1. create an A record for the URL in AD DNS, e.g. idp1.mydomain.com
    2. create an A record for the URL in Internet/External  DNS and point this to the IP address/VIP of the Web Application Proxy.
    3. create a website in IIS for simpleSAMLphp and point the configuration to the baseurlpath, of your choice, e.g. c:\inetpub\wwwroot\idp1\www
    4. add an SSL binding on the website, with Require Server Name Indication (SNI) enabled and a host header matching the URL, e.g. idp1.mydomain.com
    5. publish the new website on the reverse proxy (Web Application Proxy) using a pass-through rule
    6. configure the simpleSAMLphp configuration as described later in the post
    7. repeat for each additional new instance

Web Application Proxy (Optional)

In this lab, we’re using the AD FS Web Application Proxy (WAP) to reverse proxy HTTPS traffic to the various simpleSAMLphp endpoints. The following pass-through proxy rules are created.


External URL

Backend Server URL



















No name/URL translation is performed. Servers idp1 and idp2 are SAML 2.0 identity providers, whilst web1 and web2 are SAML 2.0 service providers.

For integration testing with AD FS, we’ll run through the following scenarios:

1.       configuring AD FS as an Identity Provider and simpleSAMLphp as a service provider

2.       configuring simpleSAMLphp as an Identity Provider and AD FS as a service provider


Scenario 1 – AD FS Identity Provider (IdP) and simpleSAMLphp Service Provider (SP)

Let’s start with simpleSAMLphp in the SAML 2.0 Service provider (SP) role.

For a basic configuration, there are a number of key simpleSAMLphp files we work with. These are:




In the authentication sources document (authsources.php), various service provider properties are defined. A single authsources.php containing information of all setups can be used and shared across multiple environments, in our case (web1 and web2), or we may elect to store settings separately, using a unique authsources.php per environment .

For expediency, I highlight the use of a common authsources.php. Each authentication module/configuration is represented by its own section in the document.

Here’s an example of two SAML service provider configurations in a test authsources.php:


‘onion1-sp’ => array(



              ‘entityID’ => NULL,

‘idp’ => NULL,

              ‘discoURL’ => NULL,


              ‘redirect.sign’ => TRUE,

              ‘assertion.encryption’ => TRUE,

              ‘sign.logout’ => TRUE,

              ‘privatekey’ => ‘web1.key’,

              ‘certificate’ => ‘web1.pem’,




       ‘attributes’ => array(




       ‘signature.algorithm’ => ‘http://www.w3.org/2001/04/xmldsig-more#rsa-sha256&#8217;,





‘onion2-sp’ => array(



‘entityID’ => NULL,

              ‘idp’ => NULL,

              ‘discoURL’ => NULL,


              ‘redirect.sign’ => TRUE,

              ‘assertion.encryption’ => TRUE,

              ‘sign.logout’ => TRUE,

              ‘privatekey’ => ‘web2.key’,

              ‘certificate’ => ‘web2.pem’,



       ‘attributes’ => array(




       ‘signature.algorithm’ => ‘http://www.w3.org/2001/04/xmldsig-more#rsa-sha256&#8217;,





Notice the different section names (onion1-sp and onion2-sp) and use of separate certificate keypairs (web1 and web2) in each section.  With the entity ID/identifier set to ‘entityID’ => NULL, simpleSAMLphp will handle the naming for the (RP) identifier of that service provider * and an entity ID is generated based on the metadata URL. In the above config, using web1.mydomain.com and web2.mydomain.com as URLs, this would translate to:





It’s also perfectly acceptable for you to choose your own identifier in the entityID section, rather than defaulting to NULL.


The IdP section refers to the entity ID (identifier in AD FS terminology) of the IdP that the service provider (SP) should contact. Like the entity ID value of  NULL used for the simpleSAMLphp service provider, this can also be set to NULL for the idp value. Where multiple identity providers exist, then the user will be shown a list of available IdPs to select from.






To corroborate the identity of the service provider, we can (optionally) digitally sign requests and a certificate is required to accomplish this.  Reference to this cert for a service provider (SP) is made in simpleSAMLphp by the privatekey and certificate setting values in the authsources.php.


By default, simpleSAMLphp uses the same certificate for token signing and encryption. The certificates comprising the private key (.key) and public key (.pem) will reside in a cert folder  made off the SimpleSAMLphp base configuration path.


‘privatekey’ => ‘web1.key’,

              ‘certificate’ => ‘web1.pem’,


In this particular configuration, we’ve elected to enable the SP to sign authentication requests (redirect/post), using the the `redirect.sign` =>TRUE option.

While use of signing and encryption is generally considered an unsightly configuration overhead and an optional, use of token signing comes into play with SAML requirements for Single Logout (SLO) and where service providers request specific functionality. As an identity provider, AD FS does expect SAM 2.0 service providers (simpleSAMLphp) to sign logout requests. With this in mind, we elect to use certificates and logout requests are signed by the SP, specifying ‘sign.logout’ => TRUE. 


To satisfy the above requirements, when creating the token signing/encryption certificate(s) for simpleSAMLphp, OpenSSL is used here to generate a certificate using the SHA2 signing algorithm. Here’s an example (2 year validity).

openssl req -x509 -nodes -sha256 -days 730 -newkey rsa:2048 -keyout my.key -out my.pem


If we’re not satisfied with simply signing tokens, then we can also require the content of the token to be encrypted, by requesting encryption using ‘assertion.encryption’ => TRUE.


Our SP is expecting that the AD FS identity provider will provide the attributes uid and mail attributes in the SAML response, as expressed by:


‘attributes’ => array(





A SHA2 (SHA256) algorithm is used to sign messages generated by the service provider. 


‘signature.algorithm’ => ‘http://www.w3.org/2001/04/xmldsig-more#rsa-sha256&#8217;


If you’re not up to date on this and as the help text in the configuration files explain, SHA-1 as a signing algorithm is largely being supplanted by use of stronger schemes.


At this point we have the makings of a basic setup authentication-wise. Additionally, simpleSAMLphp needs to be made aware of the AD FS identity provider configuration. This is collected from federation metadata belonging to the AD FS IdP and then stored in the saml20-idp-remote.php file, located in the metadata folder. This file contains configuration details for all remote SAML 2.0 Identity Providers (IdP) known to that service provider.

As we’ll see, the process for pruning metadata and converting it into a simpleSAMLphp friendly format is useable for both service providers and identity providers, thereby applicable for Scenario 2.

Getting the AD FS metadata into a simpleSAMLphp-friendly format is aided by using tools found under the installation page simpleSAMLphp (matching the baseurlpath path). Browsing to the service provider URL, e.g. https://web1.mydomain.com/www shows the simpleSAMLphp installation page.


It’s a good idea to password protect this page. This can be done by editing settings in the config.php file. The settings described therein protect the main admin page and the ensuing metadata pages.

‘auth.adminpassword’          => ‘adminpasswordtobeset’,

‘admin.protectindexpage’      => true,

‘admin.protectmetadata’       => false,


In the above, the installation page is protected and metadata left unprotected to allow automated exchange.

The installation pages allow us to perform a number of tests to prepare and configure the installation.

    1. Review the simpleSAMLphp configuration, installed/enabled modules, PHP versions etc.
    2. Use the built-in tools to parse federation metadata from identity or service providers, e.g. AD FS, subject to role, using the XML to simpleSAMLphp metadata converter.
    3. Validate the configuration by testing configured authentication sources (applies to both identity and service provider roles) via the authentication tab
    4. Observe federation metadata endpoints configured and exposed simpleSAMLphp (valid for both identity and service provider configurations)

The Federation tab on the installation page provides useful information relating to metadata and tools for assisting in the setup of federation trusts. At the foot of the federation screen, note the XML to simpleSAMLphp metadata converter.


Use this to convert federation metadata from remote sources into a simpleSAMLphp friendly format.


Here the metadata from the AD FS SAML 2.0 Identity Provider (IdP) needs to be converted for consumption by the simpleSAMLphp service provider. Download the metadata from AD FS and save it to a text file. Metadata is reachable at:

https://<YOUR FEDERATION SERVICE URL/FederationMetadata/2007-06/FederationMetadata.xml

Open the file in Notepad, copy the contents to the Metadata parser in the browser and then click on the Parse button. This will convert metadata into two formats:

(a)    saml20-sp-remote.php used where AD FS is a remote SAML 2.0 Service Provider

(b)   saml20-idp-remote.php used where AD FS is a remote SAML 2.0 Identity Provider

Since AD FS is the identity provider in this scenario, then we require Option (b). In the converted metadata section of the page, find the section relating to saml20-idp-remote.php and copy the text to clipboard. Open the saml20-idp-remote.php file found in the metadata folder of the IdP configuration, paste the contents, appending the parsed metadata into this file and save it.

NB: I’ve read on the simpleSAMLphp forums that it’s also possible to save files to the metadata folder and reference these in your configuration directly. I’ve not tested this, but if interested it’s worth checking out the simpleSAMLphp github on how this can be done.

Back at the installation page, the federation tab is also worth checking out. It shows the SAML 2.0 SP metadata endpoint information needed to configure the simpleSAMLphp relying party on the AD FS side. Here’s an example of a shared configuration file (authsources.php) representing multiple service providers.


If the simpleSAMLphp URL is reachable by the AD FS IdP, then automatic exchange of metadata is possible. Where the metadata page is password protected, then file exchange of metadata can be performed.

Let’s jump to AD FS now. We’ll add the SP instance, utilizing the “default-sp” label as our SAML 2.0  relying party of interest.


Here our endpoint is reachable across the “Internet” so we can automatically configure the RP by consuming the metadata of the service provider concerned. We create our relying party and simply take the URL mentioned above, parse it into the wizard and AD FS consumes the remote XML document automatically. Should this not be possible, say where the metadata document is password protected, or policies at the SP state otherwise, we can import the file using the AD FS wizard as mentioned earlier.

In the Issuance Transform rules on the Relying Party (RP), we can mine the claims from AD (as our claims provider), to populate the simpleSAMLphp requirements. In this example we:

          use the Send LDAP attributes as claims rule to send E-Mail Address and sAMaccountName as uid and mail, required by this relying party

          use a transform rule to send a Name Identifier in the transient format


As can be seen from the above graphic, we’re using E-Mail Address and sAMAccountName to use as incoming claims to populate in our  outgoingSAML assertion as mail and uid respectively.

Incidentally, when initiating federated logon with the SAML 2.0 protocol, a name identifier is typically used.   AD FS as an identity provider, does not send name identifier information in the format expected by simpleSAMLphp. By default, simpleSAMLphp expects a nameid format using the transient identifier (urn:oasis:names:tc:SAML:2.0:nameid-format:transient).

A quick way to get this going, albeit not conforming to SAML specs, is to transform an incoming claim rule, extracted from our AD provider, to populate as an outgoing name identifier.


In the above UI example an incoming UPN claim is transformed into a transient identifier.

Using the claims rule language, the two rules can be expressed as issuance transform rules on the simpleSAMLphp relying party as:

c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname&#8221;, Issuer == “AD AUTHORITY”]

 => issue(store = “Active Directory”, types = (“mail”, “uid”), query = “;mail,sAMAccountName;{0}”, param = c.Value);


c:[Type == “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn”%5D

 => issue(Type = “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier&#8221;, Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties[“http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format”%5D = “urn:oasis:names:tc:SAML:2.0:nameid-format:transient”);


Verifying the RP configuration, we should see both token signing and encryption certificates represented in the appropriate tabs on the relying party, populated among other settings as part of the metadata exchange.


Above, the public key of the token signing certificate, on the Signature tab of the RP.


And on the encryption tab, the public key of the encryption certificate from simpleSAMLphp.


On the Advanced tab, the secure hash algorithm should be set to SHA-256


We’re now good to go for testing the configuration within simpleSAMLphp.

Here I select the Test configured authentication sources on the authentication tab.



Then choose to test the default-sp configuration.


If the idp value for the service provider in authsources.php is set to NULL, then a drop-down list of identity providers will  be presented (otherwise we’re routed automatically to AD FS)

Here’s an example of a drop-down dialog with the Access Onion identity provider selection.


This particular identity provider is running AD FS 3.0/2012 R2. Connecting from the Internet, we’re routed to the Access Onion AD FS instance (behind the Web Application Proxy) and presented with a logon form.


As part of the logon process the appropriate user credentials are posted to AD FS, in this case user mylo.  Sent back in the SAML response is also the e-mail address of the user, read from the mail attribute in Active Directory, with a value of  nomail@accessonion  for this user.  The resultant SAML assertion can be seen in simpleSAMLphp.



Note that the name identifier is not visible on the installation page, although its presence is mandatory.

Click on Logout to check that Single Logout is also functioning and that the two federation partners are configured correctly, signing algorithms are in synch etc.


And we’re logged out, token extinguished/gone.

This is a barebones configuration. Should you wish to employ more expansive configurations, incorporating simpleSAMLphp into the PHP code of your web application (Drupal/Moodle/Joomla etc.), then refer to the simpleSAMLphp website, where there are examples to illustrate this.

Quick note on Name Identifiers

With respect to the earlier comment on the SAML protocol and NameID, when passing a name identifiers of a transient sort, it’s preferable to use an opaque identifier commuted between relying parties that doesn’t reveal the identity of the individual concerned.  To get a better insight into this with respect to AD FS and SAML, I’d suggest reading this MSDN article, as it provides examples on how privacy-bearing claims can be used.

If we wish to use an opaque reference, borrowing from the aforementioned article:

Rule 1: generate a session ID value that can be used as a transient identifier. Add this rule to the claims pipeline.

c1:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”] && c2: [Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant”]=> add (store = “_OpaqueIdStore”, types = (“http://sts.mydomain.com/internal/sessionid”), query = “{0};{1};{2};{3};{4}”, param = “useEntropy”, param = c1.Value, param = c1.OriginalIssuer, param = “”, param = c2.Value);

Rule 2:  Using the previously generated session ID, map this to the outgoing claim type  as Name ID using the transient identifier and issue the claim.

c:[Type == ”http://sts.mydomain.com/internal/sessionid”] => issue(Type=”http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier”, Issuer = c.Issuer, OriginalUser = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties[“http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format”]=”urn:oasis:names:tc:SAML2.0:nameid-format:transient”);

Now let’s look at a sample scenario where AD FS is the SAML 2.0 Servicer Provider (SP) and simpleSAMLphp is the SAML 2.0 Identity Provider (IdP)

Scenario 2 – simpleSAMLphp Identity Provider (IdP) and AD FS Service Provider (SP)

In the identity provider (IdP) capacity, simpleSAMLphp supports a number of authentication methods. These include:

·         Local authentication

·         Single LDAP/AD

·         Multi-LDAP

·         RADIUS

·         SQL

·         OpenID (FB/Twitter etc.)

·         Yubikey


That’s quite a diverse set of authentication mechanisms. There are also a number of additional custom modules developed within the community that support even more refined use cases.

We’ll look at a basic setup utilizing local authentication; namely, username/passwords stored in a flat file in the authsources.php file of the simpleSAMLphp IdP. As unglamorous as this might sound, it’s a good starting point for getting a working configuration up and running before mixing it with other more complex setups involving LDAP/RADIUS/SQL etc.

There are a number of files we work with in the identity provider configuration. These are:





On the SAML SP side, AD FS will be using simpleSAMLphp as a claims (identity) provider. We’ll also reuse the simpleSAMLphp SAML 2.0 service provider from Scenario 1 as a relying party (behind AD FS) to illustrate attribute flow.


Here’s the basic logon flow:

1.       User browses to the simpleSAMLphp Relying Party.

2.       User selects the AD FS authentication source and is redirected to AD FS.

3.      Rules logic on the AD FS determines that the user should be directly sent to the simpleSAMLphp claims provider, without showing a realm discovery page.

4.       User is redirected to simpleSAMLphp identity provider for logon where they log on as student

5.       User logs on with local identity (from authsources.php)

6.       User is redirected to AD FS for processing

7.       Claims provider rules are evaluated on the AD FS pipeline

8.       Relying Party rules are evaluated on the AD FS pipeline

9.       User is redirected to the simpleSAMLphp relying party

With all working swimmingly, we’ll end up on the simpleSAMLphp relying party page.


In this logon scenario, we’re using AD FS as Relying Party Security Token Service (RP-STS) in a “headless” capacity. It (AD FS) is not responsible for authentication but must still handle routing of the authentication request to the simpleSAMLphp relying party / test web application.  

In a multiple claims provider scenario, when sending requests via AD FS, we would normally be presented with the Home Realm Discovery (HRD) screen.


As can be seen from the above graphic, with AD FS (via AD) enabled as a claims provider, the “Access Onion” claims provider AND the simpleSAMLphp identity provider are both visible as authentication sources. For this scenario we want to exclusively send logon requests to the simpleSAMLphp identity provider, so the (home) realm selection needs to be suppressed for the simpleSAMLphp relying party/test web application. As mentioned in previous “First Look” posts on AD FS 2012 R2, this can be achieved by declaring the claims provider of choice for the relying party to use for logon in PowerShell.

Set-AdfsRelyingPartyTrust -TargetName “My Relying Party” -ClaimsProviderName @(“SimpleSAMLphp”)

This effectively takes the Access Onion Active Directory out of the mix for logon.

Back to simpleSAMLphp, we begin by enabling the SAML 2.0 identity provider functionality in config\config.php for our identity provider (idp1.mydomain.com) instance.

‘enable.saml20-idp’ => true,

Assigning true to this option enables the SAML 2.0 Identity Provider capability in this instance.

The saml20-idp-hosted.php file in the metadata folder is key for configuring the identity provider. Here’s an example (in bold) calling a local (simpleSAMLphp) authentication method known as example-userpass.


$metadata[‘__DYNAMIC:1__’] = array(

    ‘host’ => ‘__DEFAULT__’,

    ‘privatekey’ => ‘idp1.key’,

    ‘certificate’ => ‘idp1.pem’,

    ‘auth’ => ‘example-userpass’,

    ‘signature.algorithm’ => ‘http://www.w3.org/2001/04/xmldsig-more#rsa-sha256&#8217;,

    ‘authproc’ => array(1 => array(‘class’ => ‘saml:TransientNameID’,),),


You may recognize common aspects of the configuration from the SP scenario applied previously in the authsources.php. Similarly these can be applied to our identity provider configuration in the saml20-idp-hosted.php file.

The identity provider calls the example-userpass authentication scheme from the saml20-idp-hosted.php file.  

The authentication element, expressed as ‘auth’ => ‘example-userpass’, cross-references the appropriate section of the authsources.php file, containing therein a list of users.

‘example-userpass’ => array(


      // Give the user an option to save their username for future login attempts

      // And when enabled, what should the default be, to save the username or not

      //’remember.username.enabled’ => FALSE,

      //’remember.username.checked’ => FALSE,


      ‘student:pa$$st@dent’ => array(

             ‘uid’ => array(‘student’),

             ‘mail’ => array(‘student@nomail.com’),

             ‘eduPersonAffiliation’ => array(‘member’, ‘student’),


      ’employee:3mployEEP&ss’ => array(

             ‘uid’ => array(’employee’),

             ‘mail’ => array(’employee@nomail.com’),

             ‘eduPersonAffiliation’ => array(‘member’, ’employee’),




There are two test users: student and employee, with attributes uid and mail populated. As with Scenario 1, to build a federation trust with AD FS, information must be gathered via exchange of metadata to make the trust possible. For the simpleSAMLphp identity providers, extrapolated metadata from the remote AD FS service provider is stored in the saml20-sp-remote.php file in the metadata folder. On the AD FS side, we need to create a relying party trust for our test web application. We’ll re-use the service provider/relying party created in Scenario 1.

To populate the identity provider with the relevant information, the AD FS metadata file needs to be imported to the simpleSAMLphp identity provider (IdP) instance.

Open the installation page of the identity provider, e.g. https://idp1.mydomain.com/www, authenticating where necessary, and select the federation tab.  

Download the AD FS federation metadata from the metadata endpoint and save it to text file.

https://<YOUR FEDERATION SERVICE URL/FederationMetadata/2007-06/FederationMetadata.xml

Open the AD FS metadata file in Notepad, copy the content to the clipboard and then launch the XML to simpleSAMLphp metadata converter on the federation tab.


Paste the contents to the Metadata parser form in the browser and then click on the Parse button.


Scroll down to the saml20-sp-remote.php section of the web page


Copy this section of text to clipboard.


In the identity provider configuration, open the saml20-sp-remote.php file found in the metadata folder and append the parsed metadata held in clipboard to this file. Save the file.

As a SAML service provider, during passive SSO logons, AD FS makes use of a default name identifier of emailaddress. This can be seen from the metadata screenshot (circled in green):

‘NameIDFormat’ => ‘urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress’,


Given that our identity provider prefers the transient format, this can be altered using Powershell by specifying the required NameID format. More on this in a moment….


From the identity provider (https://idp1.mydomain.com/www) installation page of simpleSAMLphp, the metadata endpoint information is visible on the federation tab. This corresponds to the Entity ID of the identity provider. This URL is used to configure the claims provider on the AD FS side.


Should the simpleSAMLphp IdP endpoints be visible to support online exchange of metadata with AD FS, then the claims provider can be configured automatically. Where metadata is password protected, or the published path of the endpoint is not reachable (for security reasons), then manual exchange of metadata via file will be necessary.

We now have sufficient information to create the claims provider on the AD FS side. In the Add Claims Provider Trust wizard, the above-mentioned URL is used.


As always I recommend the use of PowerShell over the UI for automating this process. While the initial learning curve/overhead is somewhat higher, it will reduce the margin for human error and also provides documented evidence and a path on how installations/configurations are performed.

Since we are hand-waving authentication to simpleSAMLphp as claims provider, any incoming attributes will need to be processed by AD FS as part of the logon process at both the claims provider and relying party.

Firstly, we’ll override the default AD FS behavior of using SAML 1.1 name identifiers (mail) in favor of the transient identifiers mentioned earlier. To do this the expected name identifier required by the identity provider (simpleSAMLphp) can be stated in PowerShell.


Set-AdfsClaimsProviderTrust -TargetName “simpleSAMLphp Identity Provider” -RequiredNameIDFormat “urn:oasis:names:tc:SAML:2.0:nameid-format:transient”


The following SAML attributes, expressed as claims rules on the claims provider handler, are defined:


1.       Transient Name identifier

c:[Type == “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier&#8221;, Properties[“http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format”%5D == “urn:oasis:names:tc:SAML:2.0:nameid-format:transient”]

 => issue(claim = c);

2.       uid

c:[Type == “uid”]

 => issue(claim = c);

3.       mail

c:[Type == “mail”]

 => issue(claim = c);


In a completed configuration, if we were to enable debug and analytics on the AD FS server, we can see the claims processed via Event ID 1000 in the AD FS Debug tracing logs. Note the transient name identifier claim type value of _60b434c232f5cc7048fb85d80ea4c8775d38489f90 being passed when logging on using a test (student) user.


ClaimType http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier Value _60b434c232f5cc7048fb85d80ea4c8775d38489f90 ValueType http://www.w3.org/2001/XMLSchema#string Issuer https://idp1.mydomain.com/www/saml2/idp/metadata.php OriginalIssuer https://idp1.mydomain.com/www/saml2/idp/metadata.php Property[http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format] urn:oasis:names:tc:SAML:2.0:nameid-format:transient Property[http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/spnamequalifier] http://sts3a.mydomain.com/adfs/services/trust ClaimType uid Value student ValueType http://www.w3.org/2001/XMLSchema#string Issuer https://idp1.mydomain.com/www/saml2/idp/metadata.php OriginalIssuer https://idp1.mydomain.com/www/saml2/idp/metadata.php Property[http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/attributename] urn:oasis:names:tc:SAML:2.0:attrname-format:basic ClaimType mail Value student@nomail.com ValueType http://www.w3.org/2001/XMLSchema#string Issuer https://idp1.mydomain.com/www/saml2/idp/metadata.php OriginalIssuer https://idp1.mydomain.com/www/saml2/idp/metadata.php Property[http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/attributename] urn:oasis:names:tc:SAML:2.0:attrname-format:basic ClaimType eduPersonAffiliation Value member ValueType http://www.w3.org/2001/XMLSchema#string Issuer https://idp1.mydomain.com/www/saml2/idp/metadata.php OriginalIssuer https://idp1.mydomain.com/www/saml2/idp/metadata.php Property[http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/attributename] urn:oasis:names:tc:SAML:2.0:attrname-format:basic Value student Property[http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/attributename] urn:oasis:names:tc:SAML:2.0:attrname-format:basic 


Wonderful J


Meanwhile, we need to ensure on the relying party/test web application, our simpleSAMLphp relying party from Scenario 1, that the appropriate rules are applied to ensure that claims originating from the issuer (simpleSAMLphp Identity Provider) are evaluated.

The two test users defined in config.php of the identity provider will emit two SAML attributes of interest for AD FS to process (uid and mail):

‘student:studentpass’ => array(

             ‘uid’ => array(‘student’),

             ‘mail’ => array(‘student@nomail.com’),

             ‘eduPersonAffiliation’ => array(‘member’, ‘student’),


      ’employee:employeepass’ => array(

             ‘uid’ => array(’employee’),

             ‘mail’ => array(’employee@nomail.com’),

              ‘eduPersonAffiliation’ => array(‘member’, ’employee’),

To reiterate, we wish to pass identity-specific information originating from a SAML 2.0 identity provider (simpleSAMLphp), via AD FS as a SAML 2.0 Service Provider (RP-STS), to our test SAML 2.0 Service Provider/Relying Party (simpleSAMLphp). 

For the relying party, the fact that I’m using simpleSAMLphp (from Scenario 1) is merely for expediency. The application/relying party concerned may well be another application, i.e. a Cloud/SaaS or on-premise offering. However, the attributes mentioned above need to be passed by the identity provider through AD FS to the relying party application. For those not experienced with using claims providers with AD FS, this can sometimes be a little confusing.

In Scenario 1, we created a simpleSAMLphp relying party that surfaced claims from the local Active Directory as the claims provider (identity provider) using the Send LDAP Attributes as Claims claim ruleset.  This particular ruleset is not applicable to claims emitted for our simpleSAMLphp claims provider. Let’s look at the custom claims rule again:

c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname&#8221;, Issuer == “AD AUTHORITY”]

 => issue(store = “Active Directory”, types = (“mail”, “uid”), query = “;mail,sAMAccountName;{0}”, param = c.Value);


Note the reference to AD AUTHORITY. This is specifically targeting the local home Active Directory as the issuer for the claim.  When authentication is handled through the simpleSAMLphp identity provider, this rule is ignored.

Our test application (the same one used in Scenario 1) is expecting attributes uid and mail to be passed from AD FS.  We could add a single rule that states passing all claims rules to be processed by the relying party, covering the claims from the identity provider described above.


 => issue(claim = c);


This satisfies the requirement of passing the name identifier, uid and mail attributes from the simpleSAMLphp identity provider, but it also passes additional information from the AD FS RP-STS to the relying party.


Note the additional claims such as client IP, forwarded (NAT) client IP, user agent etc.

Alternatively, we could define three pass-through rules, expressly bound to the simpleSAMLphp identity provider through the issuer value.  Instead of sending all claims values, we only emit claims specific to that identity provider for the attributes concerned on the relying party rules.

1.       Name Identifier

c:[Type == “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier&#8221;, Properties[“http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format”%5D == “urn:oasis:names:tc:SAML:2.0:nameid-format:transient”, Issuer == “https://idp1.mydomain.com/www/saml2/idp/metadata.php”%5D => issue(claim = c);

2.       uid

c:[Type == “uid”, Issuer == “https://idp1.mydomain.com/www/saml2/idp/metadata.php”%5D

 => issue(claim = c);

3.       mail

c:[Type == “mail”, Issuer == “https://idp1.mydomain.com/www/saml2/idp/metadata.php”%5D

=> issue(claim = c);

Here we see the difference from the simpleSAMLphp relying party/web application in terms of claims/attributes emitted in the SAML response.


OK.. that’s it for this post. Feel free to post questions and and I’ll get back to you as soon as possible.

As ever: test, play and test a little more Smile



Exchange 2013 SP1, Outlook Web App (OWA) and AD FS

It’s over a year now since the last Outlook Web App article about integrating OWA with ADFS. In that post we explored the use of claims-based authentication with OWA in a Proof of Concept using WIF 3.5 and FedUtil. This was an unsupported setup in Microsoft eyes and, in the meantime, with the release of Windows Server 2012 R2, opportunities for supporting Exchange web applications such as OWA,  have arisen. The first, provided support via the use of a non-claims aware web application in AD FS R2 using Kerberos Constrained Delegation (KCD), utilizing the new Web Application Proxy (WAP) feature. The recent release of Exchange 2013 SP1 further expands OWA support, including native support for AD FS in the Exchange product, with claims-based authentication now possible for Outlook Web App (OWA) and the Exchange Admin Center (EAC).

To get started, I’ll refer you to a Technet article here that provides a step-by-step. I used this article as a starting point for setting up OWA/EAC with AD FS R2. These two application endpoints in Exchange (OWA and ECP) need to be represented as relying parties within AD FS.

Here’s an excerpt of the PowerShell rules required for creating the RPs:

Add-ADFSRelyingPartyTrust -Name “Outlook Web App” -Enabled $true -Notes “This is a trust for https://mail.mydomain.com/owa” -WSFedEndpoint https://mail.mydomain.com/owa -Identifier https://mail.mydomain.com/owa -IssuanceTransformRules $IssuanceTransformRules -IssuanceAuthorizationRules $IssuanceAuthorizationRules

Add-ADFSRelyingPartyTrust -Name “Exchange Admin Center (EAC)” -Enabled $true -Notes “This is a trust for https://mail.mydomain.com/ecp” -WSFedEndpoint https://mail.mydomain.com/ecp -Identifier https://mail.mydomain.com/ecp -IssuanceTransformRules $IssuanceTransformRules -IssuanceAuthorizationRules $IssuanceAuthorizationRules

The AD User and Group SIDs, together with UPN also need to be defined for each of the Exchange Relying Party applications in the form of custom claims rules: Windows Account Name (sAMAccountName)

c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”, Issuer == “AD AUTHORITY”] => issue(store = “Active Directory”, types = (“http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid”), query = “;objectSID;{0}”, param = c.Value);

Group SID (enumarate group membership)

c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”, Issuer == “AD AUTHORITY”] => issue(store = “Active Directory”, types = (“http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”), query = “;tokenGroups(SID);{0}”, param = c.Value);

User Principal Name (UPN)

c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”, Issuer == “AD AUTHORITY”] => issue(store = “Active Directory”, types = (“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn”), query = “;userPrincipalName;{0}”, param = c.Value);

On the Exchange side, via PowerShell, we specify the Relying Party Identifiers via the AdfsAudienceUris parameter and must also provide the token signing certificate thumbprint from the AD FS server.

$uris = @(“https://mail.mydomain.com/owa”,”https://mail.mydomain.com/ecp”) Set-OrganizationConfig -AdfsIssuer “https://adfs.contoso.com/adfs/ls/” -AdfsAudienceUris $uris -AdfsSignCertificateThumbprint “TOKEN SIGNING CERTIFICATE THUMBPRINT”

Don’t forget to import the token signing certificate into the Trusted Root Certificate Authorities container of your Exchange servers, otherwise you may fall foul of the following error logging on to your mailbox.


The source in pinpointing the problem here, lies in the query string of the error message https://external.mydomain.com/owa/auth/errorfe.aspx?msg=WrongAudienceUriOrBadSigningCert.

In this (my) case, the token signing certificate had not been added to the Exchange servers as a trusted cert. Equally, the wrong Audience URI can present a configuration problem. It commonly arises when a unnecessary trailing slash is added to the Relying Party Identifier when configuring in AD FS, e.g. https://mail.mydomain.com/owa/. s something to keep an eye on. The correct RP identifier would be https://mail.mydomain.com/owa.

I’ve not yet tested setting up Exchange 2013 SP1 under AD FS 2.0, but there’s nothing untoward going on here to suggest that using it as your identity provider is not possible. If you’re running under AD FS Windows Server 2012 R2 then the Web Application Proxy (WAP) adopts the proxy role for external access scenarios and also supports host name translation. For example, I make use of https://external.mydomain.com as an external URL and map this to the internal name of https://mail.mydomain.com. Be aware that matching of path-based names is not supported in the current release of the WAP, so mixing path names between externally and internally published resources is a no-no.

To illustrate this, let’s look at an example of an OK configuration:

Add-WebApplicationProxyApplication -BackendServerUrl ‘https://mail.mydomain.com/owa/’ -ExternalCertificateThumbprint ‘DD94E2ABAA123C6B6009CB42F16CE892AF96A47C’ -ExternalUrl ‘https://external.mydomain.com/owa/’ -Name ‘OWA’ -ExternalPreAuthentication ADFS -ADFSRelyingPartyName ‘Outlook Web App’

Whereas, this is a non-workable configuration.

Add-WebApplicationProxyApplication -BackendServerUrl ‘https://mail.mydomain.com/owa/’ -ExternalCertificateThumbprint ‘DD94E2ABAA123C6B6009CB42F16CE892AF96A47C’ -ExternalUrl ‘https://external.mydomain.com/mail/’ -Name ‘OWA’ -ExternalPreAuthentication ADFS -ADFSRelyingPartyName ‘Outlook Web App’

Note the use  in publishing of the same literal path  https://external.mydomain.com/owa/ in the first example, versus a rewritten one in the second https://external.mydomain.com/mail/.

If you’re contemplating the use of AD FS 2.0, then clearly host-name translation is not something that the AD FS 2.0 proxy brings to the table. Alternatively, a suitably equipped front-end load balancer may also fulfill that role.

On the subject of load balancers, this rather conveniently brings me back to new features in AD FS R2. Server Name Indication (SNI) was mentioned in the “First Looks” articles about AD FS R2 and it’s worth checking that your current load balancer/reverse proxy in front of AD FS supports SNI and is supported/enabled on the device concerned. This is becoming a pain point for many, as evidenced by various posts on the Technet forums. The move to kernel-mode (HTTP.SYS) in R2 mandates the use of SNI. Therefore, it’s worthwhile checking that:

  • your friendly neighbourhood load balancer/device in front of AD FS supports SNI
  • clients and user agents support SNI and you’re not inadvertently locking them out
  • (08/04) SSL termination endpoints (e.g. load balancer / 3rd-party reverse proxies) in front of AD FS  may be affected by the recent heartbleed bug (http://heartbleed.com), exposing vulnerable OpenSSL libraries and certificates used on those devices. Microsoft infrastructure, employing Secure Channel (SChannel)  not affected, may inadvertently become so through SSL termination endpoints on the aforementioned devices in front of AD FS. More information can also be found here (http://www.kb.cert.org/vuls/id/720951)

Accessing the OWA URL, via https://external.mydomain.com/owa and the OWA Relying Party redirects the user to AD FS for logon. In a default AD FS R2 configuration, this equates to forms-based authentication for external users.


Users accessing OWA internally, access https://mail.mydomain.com via the farm using Integrated Windows Authentication (IWA). As usual when connecting to the farm, the URL for the federation service needs to be added to the Local Intranet Zone within IE and any corresponding configuration changes made to support Kerberos for other browsers.

At this point, optional use of a clams provider (connecting to the local AD) or an MFA provider in R2 could also come into play to provide stronger authentication, should it be required. Having successfully authenticated via AD FS, we gain access to the user mailbox. image

The Exchange Control Panel (ECP) was also configured as a relying party within AD FS and within the Exchange configuration. Accessing the Exchange Admin Center remotely, with the Exchange Organization Administrator mylo, we can see the gamut of administrative console options available under federated logon.


This is one of those scenarios where it might be a good idea to apply stronger authentication (MFA)  to privileged user accounts when accessing the Exchange Admin Center. We can do this by applying policy-based access on the AD FS R2 server.

In the next post, I’ll be taking a look at strong authentication access scenarios using ActiveSync and Lync (primarily with mobile clients), before completing Part 3 of the First Looks series of AD FS R2.

SAML 2.0 IdP-Initiated Sign-On with RelayState in ADFS 2.0

Ýet another riveting title Smile Dispensing with WS-Federation, we’ll move onto looking at SAML 2.0 integration with AD FS, in particular IdP-Initiated sign-on. In the last few posts we’ve looked at how AD FS 2.0 admins can manipulate the use of the whr function to assist in the realm discovery process as part of sign-in to AD FS using WS-Federation. With AD FS 2.0 and SAML 2.0, a long-awaited feature has been support for SAML 2.0 RelayState. With Rollup 2, the AD FS team have come up with the goods. Like whr on the WS-Federation side, the use of RelayState allows us to support IdP-Initiated login from a SAML 2.0 identity provider (IdP).

Before we look at some examples, here’s a few useful tools to aid building and debugging the use of RelayState.

1. The excellent SAML Tracer plugin for Firefox (https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/)

2. A relay state generator for AD FS 2.0 to aid us in building the necessary call-back to AD FS. (https://adfsrelaystate.codeplex.com/)

3. A URL Encoder/Decoder to validate the syntax used for constructing the Relaystate query string. I used this one.. http://meyerweb.com/eric/tools/dencoder/

To get started, there’s a nice article on the Directory Services blog at Microsoft, as a backgrounder to understanding what’s going on via Rollup 2 and RelayState. http://blogs.technet.com/b/askds/archive/2012/09/27/ad-fs-2-0-relaystate.aspx.

Let’s have a look at how these scenarios may pan out. Putting my rudimentary skills in Visio 2013 to the test, here are three examples:


EXAMPLE 1: Remote SAML 2.0 Identity Provider

In the above example, our user needs to connect, via the Internet, to a remote web application that is configured as a SAML 2.0 Service Provider. This service provider is engaged in a federation trust with AD FS. AD FS as a Relying Party Security Token Service (RP-STS) has the SAML 2.0 Identity Provider (IdP), in the home realm of the user, configured as a claims provider (CP).


EXAMPLE 2 : Remote SAML 2.0 Identity Provider and Service Provider

In the above scenario, both the service provider (SP) and the identity provider (IdP) are remote to the organization. This could be a cloud / SaaS application that the RP-STS organization provides access to to both its users and the remote identity provider organization.


EXAMPLE 3 : Remote SAML 2.0 Service Provider

In the above example, the Identity Provider (IdP) and AD FS are part of the same organization.  The IdP could be an Access Management platform such as OpenAM, a remote access gateway such as a Juniper SA, or an Extranet ADFS instance with the AD FS RP-STS acting as a broker.

Access Scenario

Let’s look at some of the pre-requisites on the AD FS side:

1. Install AD FS 2.0 Rollup 2 on all instances where AD FS is involved: proxies, farm members and also third-party organizations if AD FS is installed there.

2. Add the following change to <microsoft.identityServer.web> section of the IIS web.config of all participating AD FS instances, under the /adfs/ls path.

   <useRelayStateForIdpInitiatedSignOn enabled=”true” />

In this example we’ll evaluate ADFS in a SAML 2.0 Identity Provider (IdP) role within a third party Organization, called Fie, and also as a Relying Party Security Token Service (RP-STS) within the resource organization (Foo).  Fie Users may click on a hyperlink or a bookmark that kicks off the logon process with their IdP, and through the use of RelayState, via the parameterized Relying Party Identifiers provided to the IdP and RP-STS ADFS instances, the user is sent to the service provider application.

For our web application and SAML 2.0 SP, I’m going to use cloud provider OneLogin. This will act as an application portal. Once logged on via the IdP, the user is sent to the OneLogin portal thru the RP-STS of Foo. Referring to the diagrams above, this access scenario probably best fits Figure 2. Since the web application belongs to Foo, we’re using an indirect trust involving the Foo ADFS instance as an RP-STS. Fie is a claims provider (CP) to the Foo organization ADFS and the web application is a SAML 2.0 Service Provider (SP) that trusts the ADFS instance as an Identity Provider (IdP).

Here are the service endpoints and relying party identifiers that we need to use to build the appropriate link.

Using the new notation provided in Rollup 2, two relying party identifiers (RPID) are required in order for the relay to the web application to work correctly. The RPID in ADFS terms is the identifier. For a SAML 2.0 SP, this is the Entity ID of the web application. In some scenarios the entity ID may not be sufficient and additional parameters required. Refer to the Microsoft article mentioned earlier on how this may be further encapsulated into the RelayState. I’ve included the URL encoded and decoded syntax below to give you an idea the syntax we’re forming.

Here’s the URL Decoded link, broken into three parts:

  1. &RelayState=RPID=http://sts.foo.com/adfs/services/trust
  2. &RelayState=RPID=https://app.onelogin.com/sessions/saml

Part 1 is the URL of the Identity Provider, Part 2 the query string and RelayState for the RP-STS, and Part 3 state for the SAML 2.0 SP.

Users logon on at Fie IdP, either through the AD FS proxy using forms-logon, when connecting externally or with their Windows logon ID thru the ADFS farm.  Once we’ve encoded the link, it looks like this:


And we hit the OneLogin portal:


I began the post with a smiley, so I’ll end with one.. nice feature Smile..