MicrosoftInterop
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:
- Web Browser SSO via Redirect, POST, Artifact
- Web Browser Single Logout (see the tutorial attached to this page)
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:
- Doesn't handle
<EntitiesDescriptor>
metadata files (batches), which is typically what most Shibboleth-based federations use.
- Doesn't handle multiple
<KeyDescriptor>
elements that support encryption usage, which is also common practice in Shibboleth to support key rollover (often descriptors do not carry ause
attribute at all).
- Doesn't support the use of the same certificate across multiple entities, that is, it will not consume an
<EntityDescriptor>
element containing a certificate that has already been processed. This is resolved in Update Roll Up 3. Please follow the instructions provided by Microsoft to enable it. Â (https://support.microsoft.com/en-us/kb/2790338)Â
- Does not support automated refreshing of metadata via local files.
- Can obtain metadata from a URL (and periodically refresh it), but the trust semantics of this don't appear to be defined anywhere, and it is unknown how this interacts with the
validUntil
orcacheDuration
attributes.
- There does not appear to be documentation on how the key information in metadata is actually used, but it's likely based on preliminary testing that it relies on certificates being "valid" based on some set of PKI-based assumptions such as expiration and revocation checking. The product does support self-signed certificates by virtue of including them in an imported metadata file, but how this interacts with other built-in behavior is unclear.
- If an IdP signs an assertion with a key from a certificate with a CRL Distribution Point (CDP) extension, the ADFS SP will attempt to access the CRL at the location given in the CDP.
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
- Load metadata for the ADFS system into the Shibboleth IdP.
- Define a second login handler that is capable of responding to Microsoft's non-standard authentication context:
In this configuration, the IdP returns the MS authentication context when requested by ADFS, but returns the default PasswordProtectedTransport when a SP does NOT request the Microsoft authentication context. For this functionality, we duplicate the original (unmodified) Username/Password sections inÂ
web.xml
 andÂhandler.xml
 and modify the duplicated sections to be specific to the Microsoft authentication context. Both configurations use the same Username/Password Login page, but the new section handles Microsoft authentication context, while the original section handles PasswordProtectedTransport (as well as no specific authentication method requested by the SP).
First, (if you haven't already done so) copy $(ANT_HOME)/src/main/webapp/WEB-INF/web.xml to $(IDP_HOME)/
by duplicating the unmodified Username/Password section, and then making modifications for the Microsoft authentication context. Both sections are shown below for completeness.Âconf/web.xml. Then modify web.xml
ÂExample in web.xml<!-- In conf/web.xml --> <!-- Servlet for doing Username/Password authentication --> <servlet> <servlet-name>UsernamePasswordAuthHandler</servlet-name> <servlet-class>edu.internet2.middleware.shibboleth.idp.authn.provider.UsernamePasswordLoginServlet</servlet-class> <load-on-startup>3</load-on-startup> </servlet> <servlet-mapping> <servlet-name>UsernamePasswordAuthHandler</servlet-name> <url-pattern>/Authn/UserPassword</url-pattern> </servlet-mapping> <!-- Servlet for doing Username/Password MS authentication --> <servlet> <servlet-name>UsernamePasswordMSAuthHandler</servlet-name> <servlet-class>edu.internet2.middleware.shibboleth.idp.authn.provider.UsernamePasswordLoginServlet</servlet-class> <load-on-startup>3</load-on-startup> <init-param> <param-name>authnMethod</param-name> <param-value>http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>UsernamePasswordMSAuthHandler</servlet-name> <url-pattern>/Authn/UserPasswordMS</url-pattern> </servlet-mapping>
In the new section above,Â
<servlet-name>
 (in two places) andÂ<url-pattern>
 were modified by adding "MS" to the text. Also, theÂ<init-param>
 section was added to return the Microsoft authentication context by default.Then modify $(IDP_HOME)/
conf/handler.xml
 by duplicating the unmodified UsernamePasswordÂ<LoginHandler>
 section, and then make modifications for the Microsoft assuranceÂ<AuthenticationMethod>
 to the new UsernamePasswordÂ<LoginHandler>
 as follows. Both sections are shown below for completeness.Example in handler.xml<!-- In conf/handler.xml --> <!-- Username/password login handler --> <ph:LoginHandler xsi:type="ph:UsernamePassword" jaasConfigurationLocation="file:///opt/shibboleth-idp/conf/login.config"> <ph:AuthenticationMethod>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</ph:AuthenticationMethod> </ph:LoginHandler> <!-- Username/password MS authentication login handler --> <ph:LoginHandler xsi:type="ph:UsernamePassword" jaasConfigurationLocation="file:///opt/shibboleth-idp/conf/login.config" authenticationServletURL="/Authn/UserPasswordMS"> <ph:AuthenticationMethod>http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password</ph:AuthenticationMethod> </ph:LoginHandler>
In the new section above, a new parameter "
authenticationServletURL
" was added to match theÂ<url-pattern>
 entry in theÂweb.xml
. Also theÂ<AuthenticationMethod>
 was changed to the Microsoft context to match theÂ<init-param>
 section in theÂweb.xml
.
You will need to redeployÂidp.war
 sinceÂweb.xml
 has been modified.Â
- Add an allow rule to attribute-filter.xml allowing the release of your username identifier. In this example, uid is used (urn:oid:0.9.2342.19200300.100.1.1).
- Add your Shibboleth IdP as a Claim Provider to ADFS with powershell.
- (OPTIONAL): If you would like your IDP to be the default provider install IIS Url Rewrite and add an inbound rule on the Default Web Site's /adfs/ls directory.
- Request URL: Matches the Pattern
- Using: Wildcards
- Pattern: "*"
- Action Rewrite
Rewrite URL:Â
{R:0}?whr=https://yourentityid/idp/shibboleth
- Check Append query string
- Save the rule
- Execute the following code block on the ADFS server.
# 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)
- Add ADFS metadata to the Shibboleth IdP:Â https://adfs.example.com/FederationMetadata/2007-06/FederationMetadata.xml
- (IdPv2 Only) Add http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password as an authentication method in handler.xml
- Add an allow rule to attribute-filter.xml to release some sort of username identifier. In this example, uid is used (urn:oid:0.9.2342.19200300.100.1.1)
- Add your shibboleth IdP as a Claim Provider to ADFS with powershell
# 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
- (OPTIONAL)Â When landing on the ADFS, the user will be presented with options to authenticate with either AD or Shibboleth - only one of the below needed.
- Cookie Enforcement
- To automatically select Shibboleth over AD, we insert (or overwrite) a cookie into the incoming HTTP request with a Base64 value of the EntityID for the Shibboleth IdP
- This is achieved in a load balancer or proxy performing man-in-the-middle for SSL.
- That is, it decrypts the request, performs the manipulation, re-encrypt for the backend
- There are many types of load balancer/proxy - this article will not go into any of their configuration - please use google with terms like "ssl offloading" and "set header/cookie" with the name of your load balancer/proxy.
- Key: "MSISIPSelectionPersistent"
- Value: "aHR0cHM6Ly9pZHAuZXhhbXBsZS5jb20vaWRwL3NoaWJib2xldGg=" (e.g. echo -n https://idp.example.com/idp/shibboleth | base64 )
- There has recently been a bug with some mobile apps sending a query string that ADFS gets confused with Shibboleth's answer
- if present in HTTP query:Â "wauth=http://schemas.microsoft.com/ws/", then set ADFS as login provider
- Key: "MSISIPSelectionPersistent"
- Value: "aHR0cHM6Ly9hZGZzLmV4YW1wbGUuY29tL2FkZnMvc2VydmljZXMvdHJ1c3Q=" (e.g. echo -n https://adfs.example.com/adfs/services/trust | base64 )
- To automatically select Shibboleth over AD, we insert (or overwrite) a cookie into the incoming HTTP request with a Base64 value of the EntityID for the Shibboleth IdP
- Per Relying-Party enforcement
- You can specify which Claim Provider a Relying Party must use (if nothing is set, that is when the user is asked to select from the full list of providers)
- Cookie Enforcement
# 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.
- Realm should be the entity ID of the SP.
- Return URL should be the location of the appropriate assertion consumer service, typically something likeÂ
https://sp.example.com/Shibboleth.sso/ADFS
. - Token format should be SAML 1.1.
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