Want to log on to Office365 with your email address instead of your UPN? AlternateLoginId function with ADFS on WS2012R2 is just what you’ve been waiting for.

[ UPDATE 27-FEB-2015:  Added “Known Issues” Section and link to KB article. ]
[ UPDATE 13-JUN-2014 with some additional information about infrastructure requirements. ]

A few weeks ago, Microsoft announced that an interesting new capability has been added to ADFS if you use WS2012R2.  The new function is called “Alternate Login ID” and allows you to configure your ADFS server to treat the value entered in the username field not only as a UPN or domain\username but also to perform an LDAP query for that value against a specified attribute across one or more AD forests to identify which AD has a user object which matches.  If you have a multiforest environment with Office365 and/or don’t like the idea of having to change your UPN’s to use federated AuthN with Office365, this is exactly what you’ve been waiting for. The primary goal here is to remove a common complaint about using ADFS with Office365, which is an assumption on the part of Office365 that the userPrincipalName value in your AD is the same as a person’s UPN in Office365.  For most customers that I have worked with on implementing Office365 with federated AuthN, this has required changing the UPN’s of users who will use Office365 services which is a relatively low-risk action but still presents execution challenges. The new function is enabled by running a command like this one:

Set-AdfsClaimsProviderTrust -TargetIdentifier "AD AUTHORITY" -AlternateLoginID mail -LookupForests contoso.com,fabrikam.com

This command specifies what the attribute name is that should be used — mail is recommended — and the list of AD forests that the lookup should be performed against.  I’ve found that you need to specify the forest root domain if the target AD is a multidomain environment even if the users that you’re looking for are in a subdomain. The ADFS server(s) must be able to reach Global Catalog servers in the target forest so make sure that your A records for the global catalogs (gc._msdcs.contoso.com) are correct. This document has lots of details about how this works and a nice flow chart of how authentication is performed with AlternateLoginId enabled, but what essentially happens is:

  1. User provides username and password strings to ADFS
  2. ADFS performs an LDAP query against the AD forests provided to see if any of them has a user where the specified user attribute (like “mail”) matches the username value provided by the user:
    1. IF one and only one AD responds with a matching user object, ADFS proceeds with authentication against that user object.
    2. IF no match is found in any AD, ADFS tries again, treating the username string provided as a UPN or domain\username combination.
    3. IF more than one AD responds with a match, the authentication fails and an error message is logged.

A new claim is returned by ADFS called http://schemas.microsoft.com/ws/2013/11/alternateloginid which contains the alternate login ID.

HOWEVER, turning on AlternateLoginId is not enough by itself to make things work with Office365 and ADFS!  You still need to make sure that Office365 UPN’s are configured correctly and also make a configuration change to the claim rules created in ADFS for Office365 to make everything line up. Office365 UPN must match the value that ADFS is sending for the alternateLoginId In order to log in to Office365, the federation service needs to send a claim containing the userPrincipalName (UPN) of the user.  The default configuration for ADFS is to simply send the UPN of the on-premise user to Office365, which is why you need to make sure that the UPN in AD matches their Office365 UPN.

The default behavior of the Dirsync tool is to set the UPN of a user in the cloud to match their Active Directory UPN so everything works fine if your AD UPN’s use routable domain names and you use an unmodified ADFS environment. HOWEVER, with AlternateLoginId enabled, ADFS will be sending the value of the specified attribute — usually “mail” — as the UPN so we need to make sure that users in the cloud have their UPN matching that attribute and not their active directory UPN.  While it is possible — but not supported — to tweak the configuration of Dirsync to map these attributes, Dirsync may not be able to make this change because there are limitations on the ability to change a user’s UPN in Azure AD.

ADFS Claim Rule Change required: You must also update ADFS to send the value of the mail attribute as the UPN value instead of sending the userPrincipalName.  To do this, open the first claim rule for Office365 on ADFS and change the default rule from this:

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]
 => issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/claims/UPN", "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID"), query = "samAccountName={0};userPrincipalName,objectGUID;{1}", param = regexreplace(c.Value, "(?<domain>[^\\]+)\\(?<user>.+)", "${user}"), param = c.Value);

… to this (changed value is in red):

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]
 => issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/claims/UPN", "http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID"), query = "samAccountName={0};mail,objectGUID;{1}", param = regexreplace(c.Value, "(?<domain>[^\\]+)\\(?<user>.+)", "${user}"), param = c.Value);

ImmutableID note:  If you are using a custom identity sync solution to Office365 such as FIM with the Azure Active directory Connector and your implementation requires you to provide your own ImmutableID value, you will need to update the value for the immutableId claim sent by ADFS as well as the UPN claim.

Infrastructure and connectivity requirements.  (Added 13-JUN-2014)

  • The “lookupdomain name(s) specified must point to the forest root domain, even if the domain that the target users are in is a subdomain.
  • You must be able to reach a server that is a global catalog in the target forest root domain on port 389 in order for the LDAP lookup to succeed.
  • Make sure that all DNS SRV records are in good shape for all AD’s in play.

Prerequisites:  KB2919355, which is a major update for WS2012R2, adds the new capability.  Also, you must install KB2919422 first.

References for additional detail:  Configuring Alternate Login ID and another detailed description of how AlternateLoginId works.

Known Issues:  (Added 27-FEB-2015)
There are a set of known issues that occur when the UPN of the user in AzureAD/O365 doesn’t match the actual UPN of the on-premise user that is associated with it.  Applications which make their own direct calls to AD after authenticating to AAD, such as the desktop Lync client, are most likely to be affected.  This can result in multiple authentication popups being presented to the user where the user must enter their on-premise identity — either domain\username or actual on-premise UPN — to proceed.  For more information on this, see this KB article.


Configuring Cisco WebEx Meeting Server to work with ADFS 2.0+

Like so many other things I’ve written about, this is another example of where I was unable to find a solid set of instructions online about how to do something and had to assemble a working solution from a number of fragments spread across vendor-provided information, blog posts and cries for help posted in online forum threads.  Hopefully this can spare at least a few others from having to go through the same thing.

This procedure has been used to create a system that worked on the “first try” so I know that it works.  It’s possible that this process could be further refined with some additional testing.

This post is targeted to the on-premise version of the Cisco WebEx meeting server, not the hosted (SaaS) version.  I believe that most of what is here should be applicable to the hosted version but there are apparently some differences in the configuration screens that are used for the hosted version.

In this case, It’s assumed that you have an existing ADFS setup (version 2 or 3) which is working properly.  If you’re not confident about this, make sure that all is well before proceeding.

Before you begin, you need to capture some information about your ADFS setup:

  • Export the public key for the Token Signing certificate that your ADFS setup is using and save it to a file.  This can be done via the Certificates MMC snapin.  IMPORTANT:  The certificate must be exported in base64 format, not the default DER format.

  • Capture the Federation Metadata for your ADFS environment to a file as well.  The easiest way to do this is to go to the metadata URL for your ADFS server (usually https://adfs.contoso.com/FederationMetadata/2007-06/FederationMetadata.xml) via a web browser.  What you’ll get back is a blob of XML that your browser probably won’t display properly.  Even if the page appears to be blank, choose “view source” for the page and you should see all of the XML.  Save that to a file.

Once you’ve got those two files (the public key for the token signing certificate and the metadata XML for your ADFS setup), the process starts on the WebEx side…

  1. Import the public key for the signing certificate into WebEx using the “Import Certificate” button under “SSO IdP certificate” on the SSO configuration screen.
  2. On the “Federated Web SSO” configuration page, import the metadata file from ADFS using the button labeled “Import SAML Metadata”.  This will populate some of the fields on the configuration screen for you.
  3. Review and update the fields on the WebEx SSO settings page so they match the list below.  Some of these are already filled in for you based on the ADFS metadata file.
  • SP Initiated should be selected (at the top) and not “IdP Initiated”
  • Target Page URL Parameter name should be TARGET
  • SAML Issuer (SP ID) should be your WebEx URL service name (https://mywebex.contoso.com)
  • Issuer for SAML (IdP ID) should be your ADFS service name (https://adfs.contoso.com)
  • Customer Service SSO Login URL should be populated with an endpoint for your ADFS service like https://adfs.contoso.com/adfs/services/trust
  • NameID Format should be “Unspecified” (drop-down menu)
  • AuthnContextClassRef : Paste in the string below, replacing whatever is already in the box.  Make sure that no line breaks sneak in during the copy/paste process.
  • urn:federation:authentication:windows;urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
  • Single Logout should be DISABLED (unchecked)
  • Auto Account Creation and Auto Account Update should be enabled or disabled according to your local policies.

Once the fields on the SSO Configuration screen for WebEx have been set up as described above, use the button on the page to export the SAML metadata.  This will create a file named webex_SP_saml2_metadata.xml.  Save this file and copy it to your ADFS server.

Now, on the ADFS server…

Create the relying party trust for WebEx in ADFS by performing the following steps:

  1. In the ADFS management tool, right-click the Relying Party Trusts folder and select “Add Relying Party Trust…”
  2. On the “Select Data Source” page, click “Import data about the relying party from a file” and use the Browse button to import the webex_SP_saml2_metadata.xml file that you exported from WebEx.  Then click Next.
  3. On the “Specify Display Name” page, type a display name for the relying party (like “WebEx”) and click Next.
  4. [ If you are using WS2012R2, the next screen will ask about multi-factor authentication.  Select “I do not want to configure…” and choose next. ]
  5. On the “Choose Issuance Authorization Rules” page, leave the default value “Permit all users to access…” selected and click Next.
  6. Review the summary screen, click Next and then Close to complete the wizard.  This will launch the claim rules editor.

Next, create four claim rules in ADFS as described below:

Rule #1:  “WebEx Name ID Claim”

This rule sends the user’s e-mail address as the “Name ID” claim.  The Name ID claim is a very common requirement for applications using federated SSO and is nearly sufficient all by itself for a successful login to WebEx.

  1. Choose “Send LDAP Attributes as Claims” and hit Next
  2. Enter the display name “WebEx send Name ID”
  3. Select “Active Directory” for the attribute store
  4. On the LEFT SIDE, choose “E-mail Addresses” from the drop down.  You may have to click on the down-arrow a couple of times before the list populates.
  5. On the RIGHT SIDE, choose “Name ID” from the drop down.
  6. Click “Finish” to save the rule.

Rule #2:  WebEx AutoCreate”

These four rules send the user’s email address for custom claims named “uid” and “email” and also their first and last names.  These values are used by WebEx to create an account for the user if they are not currently present in the system and “Auto Account Creation” is enabled.

  1. Choose “Add Claim Rule…,”
  2. Select “Send LDAP Attributes as Claims”
  3. Set the display name to “WebEx Auto Create User”
  4. Add the FOUR claims below, one per row.  For the left side, use the drop-down to select the item specified.  On the right side, type in (not select) the value listed without the quotes.
    * E-mail Addresses –> “uid”
    * E-mail Addresses –> “email”
    * Given-Name –> “firstname”
    * Surname –> “lastname”
  5. Click Finish to save the rule.

Rule #3:  “WebEx AutoUpdate”

This rule sends the value of the updateTimeStamp on the user’s AD object as a custom claim named whenChanged.  If Auto Update User is enabled, WebEx apparently uses this value to tell when a person’s basic information (i.e. their last name) has changed so it can update its record for the user to match.

  1. Click “Add Rule…”
  2. Choose “Send Claims using a custom rule” from the drop down (it’s at the bottom of the list).
  3. Enter “WebEx Auto Update” for the display name
  4. Paste the text in the box below into the claim rule window:
  5. c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"] => issue(store = "Active Directory", types = ("updateTimeStamp"), query = ";whenChanged;{0}", param = c.Value);
  6. Click “finish” to save the rule.  If you get an error, make sure that the rule was pasted correctly.

Rule #4 : “WebEx send authenticationMethod”

This is one of the “gotchas” that apparently is not well documented.

This rule sends the value “urn:federation:authentication:windows” as a claim named http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod.  This value must match one of the values listed in the AuthnContextClassRef field on the WebEx side.  In our case, we found that the default value provided by ADFS for a successful logon did not match what was in the AuthnContextClassRef and adding this claim brought them into alignment.  It may be that your own ADFS setup is sending a value which matches the value that is the default in the WebEx SSO but specifying it explicitly on both sides makes sure that things line up.

  1. Click on “Add Rule…”
  2. Choose “Send Claims using a custom rule”
  3. Enter “WebEx send authenticationMethod for the display name
  4. Paste the text in the box below for the claim rule:
  5. exists([Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"])
      => issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "urn:federation:authentication:windows");
  6. Click “finish” to save the rule.  If you get an error, make sure that the rule was pasted correctly.

Now, you should be able to go to your WebEx URL (https://mywebex.contoso.com), have your authentication handled by ADFS and then land back in WebEx as an authenticated user.

[ Revised 26-FEB-2015: Minor cleanup and wording. ]

Misdirection via ADFS Config Wizard Error Dialogs

While doing the configuration of the first federation server for ADFS at a customer site, we encountered the error message below.

After spending quite a while fruitlessly testing permissions, looking at NTDS diagnostic logs, and verifying the server’s trust relationship with the AD was correct, we noticed that in the AD, the “Program Data” container was actually an OU and not a container.

My theory is that sometime in the past someone deleted the Program Data container (accidentally?) and recreated it as an OU.  After deleting the (empty) impostor OU and creating a replacement container properly, all was well.

You do not have sufficient privileges to create a container in Active directory at location CN=xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx,CN=Microsoft,CN=Program Data,DC=xxxxxxx,DC=xxx for use with sharing certificates.  Veriy that you are logged on as a Domain Admin or have sufficient privileges to create this container, and try again.
You do not have sufficient privileges to create a container in Active Directory at location CN=xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx,CN=Microsoft,CN=Program Data,DC=xxxxxxx,DC=xxx for use with sharing certificates. Verify that you are logged on as a Domain Admin or have sufficient privileges to create this container, and try again.

Another person who had a similar issue blogged about it here, which includes instructions on how to properly create the Program Data container.

What I’m taking away from this is an understanding that this error message appears to be thrown any time there is an exception during this step of the configuration process so you can’t take the error text at face value. :-)