The Shibboleth V2 IdP and SP software have reached End of Life and are no longer supported. This documentation is available for historical purposes only. See the IDP v4 and SP v3 wiki spaces for current documentation on the supported versions.

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 a use 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 or cacheDuration 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)/conf/web.xml. Then modify web.xml by duplicating the unmodified Username/Password section, and then making modifications for the Microsoft authentication context. Both sections are shown below for completeness. 

      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)

# 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
    • 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)
# 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.)

Sample metadata for Access Control Service
<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

  File Modified

Microsoft Word Document ADFS and Shib 0.81.docx AD FS 2.0 and Shibboleth 2 integration tutorial

Oct 22, 2010 by trscavo@internet2.edu

PDF File ADFS_and_Shib.pdf

Oct 22, 2010 by peter