Support and Terminology between ADFS and Shibboleth

ADFS V1

The first ADFS release is limited to support for the WS-Federation "passive" profile and does not support SAML, so interoperability is confined to the use of Shibboleth extensions for that protocol, which are currently only available for the SP.

A guide for how to configure and use the V2 SP extension can be found at NativeSPADFS.

ADFS V2

The second generation ADFS software supports part of the SAML 2.0 standard as well as WS-Federation. In addition to the material at NativeSPADFS, the following information is relevant to the use of SAML 2.0.

Usable Profiles

To the best of our knowledge, the following SAML 2.0 profiles and bindings can be used:

Metadata

An ADFS instance generates signed metadata on-the-fly at well-known location /FederationMetadata/2007-06/FederationMetadata.xml. Presumably this metadata file contains a single <md:EntityDescriptor> element with both <md:IDPSSODescriptor> and <md:SPSSODescriptor> roles.

A Shib IdP will consume this metadata straightaway. However, there is no support for metadata extensions in ADFS, and therefore it can not produce the scope extensions element required by the Shib SP.

While ADFS generates metadata that is generally compatible with and usable by the Shibboleth IdP or SP, the metadata tends to include a lot of verbose extensions related to WS-Federation and WS-Trust, so it tends to be difficult to read. As a consumer, it handles most basic metadata generated by or prepared for Shibboleth sites.

The following caveats are believed to exist:

Due to these limitations, it's likely that meaningful interoperability will involve filtering or generating specialized metadata for consumption by ADFS, possibly with specialized tools written or adapted from other software.

IdP Discovery

The ADFS SP has an embedded discovery mechanism. Every IdP configured into ADFS appears on a drop-down menu presented to the user.

There is no explicit support for the standardized discovery protocol supported by Shibboleth. The design of ADFS is such that web sites refer users to a local "STS"/federation service that in turn offers some set of authentication options that can include remote/federated IdPs. There's probably some kind of template that can be used to control the UI for this.

NameIdentifiers

The ADFS GUI contains special options for mapping outgoing claims to a SAML NameID, and the reverse. There may or may not be finer grained control of the NameQualifier attributes, but this requires some kind of custom rule that sets the attributes using a custom property syntax that isn't well documented.

It's possible to map claims like the Infocard-flavored PPID into a SAML 2.0 "persistent" NameID, but the semantics and rules for generating and managing it would be limited to however PPID is handled. Probably a custom connector for supplying a claim could be written to generate and manage them more like Shibboleth does, but it may not have access to the right information and that API has not been investigated.

For most applications, usual Shibboleth practice of ignoring the NameID is probably a good way to go, but the "persistent" NameID case could be a problem.

The ADFS SP can consume a SAML V2.0 Persistent Identifier (including the NameQualifier and SPNameQualifier values) but its ability to consume the eduPersionTargetedID attribute syntax has not been demonstrated. The former is favored for SAML 2.0 deployments in any case.

Attributes

The support for claims mapping is flexible enough to generate standardized attributes, but the IdP lacks support for controlling the NameFormat attribute. Shibboleth defaults assume "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", but the SP now allows simplified handling of attributes with an unspecified/missing NameFormat, so no extra work is needed to map them.

There is an undocumented syntax for setting the NameFormat as a custom property of the outgoing claim.

An example of this based on a previously defined claim definition:

c:[Type == " urn:oid:2.5.4.42" ] => issue(Type = "urn:oid:2.5.4.42", Value = c.Value,
    Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/attributename"] =
        "urn:oasis:names:tc:SAML:2.0:attrname-format:uri");

It appears to be impossible to set this on all claims extracted from a directory or database, and instead requires pulling each claim one at a time, or perhaps layering a set of derived claims on top of a set that have been extracted from a directory, if that's possible. Either way requires a lot of custom configuration and probably scripting to do so.

There is apparently ongoing work to reverse engineer the syntax for this functionality and it may be possible to get around the limitations that were identified in many respects.

The SP side is less of a problem, but has the slight bug that it appears to ignore the NameFormat when processing incoming claim identifiers, which is technically broken, since SAML attributes are only unique in name when both Name and NameFormat are combined.

AuthnRequest Issues

So far, it appears that there is no way to make ADFS2 support forced authentication (forceAuthn).

Response Issues

Nothing known at this time.

Logout Issues

ADFS appears to have a bug in the processing of extensions, which in SAML have optional semantics. A 2.5 and later SP by default includes a standard extension in its logout request messages that isn't being ignored. Adding asynchronous="false" to the <Logout> element will disable the extension.

Using Shibboleth IdP as the authentication source for ADFS

Better integration with Microsoft products (like Office 365) may require the use of ADFS, though this is likely to be less true over time due to the general move to browser-based login for all applications. These instructions are to enable ADFS to pass authentication to the Shibboleth IdP for WS-Federation relying parties (passive / web-based), and leave WS-Trust (active / non-web) to authenticate against ADFS. In this use case, we only pass the uid (username) from Shibboleth and then do further attribute lookups in Active Directory when defining "relying parties" (or SPs) - this works well when only integrating ADFS with Microsoft Products.

ADFS v1

Not applicable, since the Shibboleth IdP does not support WS-Federation.

ADFS v2

# Change these to match your environment
$name = "Shibboleth IdP" 
$metadata = "https://idp.example.com/idp/profile/Metadata/SAML"
$domainprefix = "AD-DOMAIN-PREFIX\"


# Map and Tranform "uid" (username) to a Windows Account Name (e.g. "AD-DOMAIN-PREFIX\username") so AD can perform it's user matching for attribute lookups
# You can extend this to pass further attributes if required, however in our use-case we rely on Active Directory to do further attribute look ups when defining relying parties as we only integrate ADFS with Microsoft Products
$claims = "c:[Type == `"urn:oid:0.9.2342.19200300.100.1.1`"] => issue(Type = `"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname`", Issuer = "AD AUTHORITY", OriginalIssuer = c.OriginalIssuer,Value = `"$domainprefix`" + c.Value, ValueType = c.ValueType);"
 
$signAlg = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"


#Warnings about incompatible elements are generally OK 
Add-ADFSClaimsProviderTrust -Name $name –MetadataURL $metadata -AcceptanceTransformRules $claims -SignatureAlgorithm $signAlg -MonitoringEnabled $true

ADFS v3 (2012r2)

# Change these to match your environment
$name = "Shibboleth IdP" 
$metadata = "https://idp.example.com/idp/profile/Metadata/SAML"
$domainprefix = "AD-DOMAIN-PREFIX\"


# Map and Tranform "uid" (username) to a Windows Account Name (e.g. "AD-DOMAIN-PREFIX\username") so AD can perform it's user matching for attribute lookups
# You can extend this to pass further attributes if required, however in our use-case we rely on Active Directory to do further attribute look ups when defining relying parties as we only integrate ADFS with Microsoft Products
$claims = "c:[Type == `"urn:oid:0.9.2342.19200300.100.1.1`"] => issue(Type = `"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname`", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer,Value = `"$domainprefix`" + c.Value, ValueType = c.ValueType);"
 
$signAlg = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"


#Warnings about incompatible elements are generally OK 
Add-ADFSClaimsProviderTrust -Name $name –MetadataURL $metadata -AcceptanceTransformRules $claims -SignatureAlgorithm $signAlg -MonitoringEnabled $true
# Determine the Name of the Claims Provider you want to use
> Get-AdfsClaimsProviderTrust | ft Name, Identifier
 
Name             Identifier
----             ----------
Active Directory AD AUTHORITY
Shibboleth IdP   https://example.com/idp/shibboleth


# Determine the Identifier of the Relying Party you want to use
>Get-AdfsRelyingPartyTrust | Format-Table Identifier, ProtocolProfile, ClaimsProviderName
 
Identifier                                                                     ProtocolProfile ClaimsProviderName
----------                                                                     --------------- ------------------
{https://sp.example.com}                                                       WsFed-SAML      {}
{urn:ms-drs:adfs.example.com}                                                  WsFed-SAML      {Active Directory}
{https://login.microsoftonline.com/extSTS.srf, urn:federation:MicrosoftOnline} WsFed-SAML      {Shibboleth IdP}




# Set it
Get-AdfsRelyingPartyTrust -Identifier:'https://sp.example.com' | Set-AdfsRelyingPartyTrust -ClaimsProviderName:@('Shibboleth IdP')


Access Control Service

Access Control Service does not support SAML, but supports the WS-Federation Web (passive) requestor profile, so can be used as an identity provider with the Shibboleth SP as described here.

Access Control Service does not appear to be able to understand metadata generated by the SP, or to generate metadata that the SP can understand, so you should be prepared to manually configure the SP's details in Access Control Service, and to hand-craft metadata for Access Control Service.

The configuration parameters you will need for Access Control Service are as follows.

Hand-crafted IdP metadata will look something like this. (Replace entity ID, signing key and SSO service location as appropriate.)

<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://example.accesscontrol.windows.net/">
  <IDPSSODescriptor protocolSupportEnumeration="http://schemas.xmlsoap.org/ws/2003/07/secext">
    <KeyDescriptor use="signing">
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:X509Data>
          <ds:X509Certificate>...base64 signing key...</ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </KeyDescriptor>
    <SingleSignOnService Binding="http://schemas.xmlsoap.org/ws/2003/07/secext"
        Location="https://example.accesscontrol.windows.net/v2/wsfederation"/>
  </IDPSSODescriptor>
</EntityDescriptor>

Attachments