NOTE: I updated this 10/9/2013 because some of the Url references I had below had changed between when I did it (when AAD was in preview) and now (RTM).
The Azure Active Directory (AAD) team has made the first release of their product. Along the way they’ve added functionality that allows you to configure AAD as an identity provider in ACS. With these features, AAD and ACS become a natural combination to use with SharePoint when you are interested in securing your site using SAML claims.
You may question using AAD, when you’ve obviously got Active Directory to begin with. In my own experience, the majority of people using SAML are also using ADFS and AD for their identity provider. In those cases, as well as when you want to share a common directory store and authentication provider across multiple web applications (SharePoint or otherwise), AAD is a natural fit. The real value add with AAD is that unlike most other SAML providers you use with SharePoint, it has a built-in queryable directory. You still end up having to write a custom claims provider, but the Graph API built on top of AAD gives you the hooks you need to wire up your claims provider, which is a big advantage over what we typically have to work with.
In order to configure SharePoint 2013 with AAD, it uses a lot of steps and concepts that you’re already familiar with if you have configured SharePoint with SAML authentication before, or if you’ve read my blog before on SAML, ACS, ADFS and SharePoint. I’m going to use a combination of pointers to other postings, some copy and paste from some other blog posts (mine and others), and some new content. Here’s the process for getting this set up; for the first four steps I recommend you read Vittorio’s blog on configuring AAD with ACS at http://www.cloudidentity.com/blog/2012/11/07/provisioning-a-directory-tenant-as-an-identity-provider-in-an-acs-namespace/.
One quick point here – why use ACS? There is a capability to have AAD act as an identity provider on its own (see the walk through here: http://msdn.microsoft.com/en-us/library/windowsazure/dn151790.aspx). Well the problem we need to work through is that AAD uses SAML 2.0, and SharePoint only works with SAML 1.1. Since ACS understands both formats, we will use it as the intermediary to transform the token formats between SharePoint and AAD.
So, to create or reuse an ACS tenant, use the new Azure Portal at https://manage.windowsazure.com. You’ll see “Active Directory” listed in the left navigation pane. Click on it and you can see your existing ACS tenants and use one of those, or create a new one. Once you have the tenant you want to work with, go ahead and click on it, then click on the Manage button in the bottom bar. That takes you to the older ACS tenant management page. In my case I created a new tenant called DreamSwirls, so when I click on the management button it takes me to https://dreamswirls.accesscontrol.windows.net/v2/mgmt/web.
I’ll assume that you haven’t created a tenant yet, but if you have already then you can certainly reuse it. You’ll just want to make sure you follow the step below about configuring directory sync and SSO. To create a tenant go to https://account.windowsazure.com/organization to set one up. If you already have a tenant you can go to https://manage.windowsazure.com/ to manage your existing tenant. Vittorio’s post has more details if needed. In my case, I created a new tenant called DreamSwirls.
This step I’m not going to cover in any detail because Vittorio’s post does so beautifully. Read his post to get the link to download the MSOL PowerShell tools as well as the four lines of PowerShell you need to create the Service Principal. Spoiler alert – it’s easy! :-) NOTE: I downloaded the MSOL Powershell from http://onlinehelp.microsoft.com/en-us/office365-enterprises/hh124998.aspx.
I tried but could not think of any more acronyms to add to step 4. Suffice to say this step is also pretty easy, and you can get the blow by blow steps on Vittorio’s blog. In a nutshell though, you’re just going to head over to the management page for your ACS tenant, as described at the end of Step 1. Click on the Identity Providers link in the left pane and then click on Add to create a new IdP. Select the option to create a new WS-Federation identity provider and then click the Next button. In the new Identity Provider pages you’ll paste in the link to the Federation Metadata XML file from AAD; by default this is at https://accounts.accesscontrol.windows.net/yourNewAadTenantName.onmicrosoft.com/FederationMetadata/2007-06/FederationMetadata.xml. In my case, since my tenant name is “DreamSwirls”, my metadata Url is https://accounts.accesscontrol.windows.net/dreamswirls.onmicrosoft.com/FederationMetadata/2007-06/FederationMetadata.xml. That’s really all you need to get your AAD tenant registered in ACS and ready to use by SharePoint.
The guidance for doing these steps is happily progressing and getting much better over time. When you visit your AAD tenant at https://activedirectory.windowsazure.com/default.aspx, there is a link on the home page that says “Integrate with Active Directory”. I’m not going to cover this in any real detail here, because there are several steps, some downloadable tools required, and excellent instructions in the AAD tenant. In a nutshell though what you’ll end up doing is adding your domain to your tenancy, which will require you adding a simple TXT entry to your DNS so it can be validated that you own it. Then you’ll download and configure directory synchronization between your local domain and your AAD tenant – that’s how all of your AD users and groups will get replicated up to the cloud. Finally, you’ll configure SSO, and when you do that you’ll provide the Url to your ADFS farm where your domain users can authenticate. That allows you to manage your accounts, groups, and passwords in your local AD as you are used to doing. When you’re done with this step you should be able to see all your AD accounts in your AAD tenant, make one of them a global administrator, and then log into the tenant with the AD credentials for that user against your ADFS farm.
UPDATE 10/9/2013: You can now manage your AAD tenant directly in the Windows Azure Portal at https://manage.windowsazure.com.
Now that I have my IdP all set up, I still need to create a new relying party in ACS for SharePoint. I covered this in my post here: http://blogs.technet.com/b/speschka/archive/2011/05/05/federated-saml-authentication-with-sharepoint-2010-and-azure-access-control-service-part-1.aspx. Scroll down to step #3 for step by step instructions to create the relying party for SharePoint in ACS. The main things to remember are that you want to configure the Return URL to be https://yourSharePointSite/_trust/, and to write down the realm you use because you’ll need that in Step 8 when you create an SPTrustedIdentityTokenIssuer; in my case I’m using “urn:sharepoint:aad” as the realm. In the identity provider section of the ACS relying party configuration, check the box next to your AAD IdP. Also remember to configure the Token Format to be SAML 1.1.
UPDATE: As Ken mentions in the comments below, you should increase the token lifetime to a bigger value. It's 10 minutes by default, and your login token window is 10 minutes by default, so if you don't change it you will just end up constantly looping back and forth between SharePoint and ACS to authenticate. Set it to a number that's reasonable for your environment; I normally use 10 hours but your mileage may vary.
Finally, leave the box checked to Create A New Rule Group at the bottom of the page
For reasons I’ll explain later on in this post, you want to first create a rule that will just pass through all claims from the IdP to SharePoint. To do that, on the ACS management page click on Rule Groups. When you created the relying party you checked the option to create a new rule group. You should see a new rule group now that has a name that “Default rule group for nameOfMyRelyingParty”; click on that link. Click the Add link to create a new rule. The Identity Provider drop down should have your AAD IdP selected already. This is really all you need to do; you can enter a description if you wish like “Passthrough all claims from AAD”, then click the Save button and that takes you back out to the Edit Rule Group page.
When AAD released, they also made one other important change you’ll find in the release notes (http://msdn.microsoft.com/en-us/library/windowsazure/dn168860.aspx), which is that they no longer expressly include the UPN claim; it’s value however is included in the Name claim. As you get into building the custom claims provider to use with AAD, you’ll see that UPN is one of the two ways in which you can query for user attributes (the other is object ID or oid, and is generally not useful for the humans). In order to get the UPN claim to us then we’ll create an additional claim mapping in our Rule Group to send the value of the Name claim back in a UPN claim. To do that:
Once you’ve done this you’re returned to the Edit Rule Group page and you can just click the Save button again to keep your changes.
This step is fundamentally the same process as you did in SharePoint 2010. It’s always a little trickier with ACS though, specifically getting the token signing certificate. I covered had to do that in this post: http://blogs.technet.com/b/speschka/archive/2011/05/05/federated-saml-authentication-with-sharepoint-2010-and-azure-access-control-service-part-1.aspx. Scroll down to step 6 and look at c) for details on how to get the token signing certificate and save it to disk. Once you have it saved to disk then it’s a fairly straightforward and familiar set of PowerShell commands to create your SPTrustedIdentityTokenIssuer. Here it is, with a few comments to follow:
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("c:\dsAcsTokenSigning.cer")
New-SPTrustedRootAuthority -Name "ACS Dream Swirls Token Signing Certificate" -Certificate $cert
$map = New-SPClaimTypeMapping -IncomingClaimType " http://schemas.microsoft.com/ws/2008/05/identity/claims/upn" -IncomingClaimTypeDisplayName "UPN" -SameAsIncoming
$map2 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" -IncomingClaimTypeDisplayName "Role" -SameAsIncoming
$map3 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" -IncomingClaimTypeDisplayName "EmailAddress" -SameAsIncoming
$map4 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" -IncomingClaimTypeDisplayName "GivenName" -SameAsIncoming
$map5 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" -IncomingClaimTypeDisplayName "SurName" -SameAsIncoming
$map6 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/jobtitle" -IncomingClaimTypeDisplayName "JobTitle" -SameAsIncoming
$map7 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/office" -IncomingClaimTypeDisplayName "Office" -SameAsIncoming
$realm = "urn:sharepoint:aad"
$ap = New-SPTrustedIdentityTokenIssuer -Name "AAD" -Description "ACS Using Azure Active Directory Identity Provider" -realm $realm -ImportTrustCertificate $cert -ClaimsMappings $map,$map2,$map3,$map4,$map5,$map6,$map7 -SignInUrl "https://dreamswirls.accesscontrol.windows.net:443/v2/wsfederation" -IdentifierClaim " http://schemas.microsoft.com/ws/2008/05/identity/claims/upn"
Here are the comments: I saved the token signing certificate from ACS as c:\dsAcsTokenSigning.cer, so that’s what I referred to in my first line of PowerShell. I also have to add that certificate to my list of trusted root authorities, as I do with all token signing certificates, so that was the next line of PowerShell. The claim mappings should be straightforward, but I’ll explain a little more about that in a bit. The $realm variable is what I defined in my relying party configuration in the Step 6.
Secondly, not all of these claim mappings in the PowerShell will work. What I mean by that, is not all of those claims are going to be returned. Even though ACS is configured to pass through all of those claims from AAD, your AAD tenant will not return all of those claims. When AAD redirects you to authenticate against ADFS, it won’t just do a pass through itself of the claims it gets back. The claim set I am currently getting back (and this is subject to change as AAD updates the service) based on my claim mappings looks like this:
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: firstname.lastname@example.org://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: email@example.com://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname: Stevehttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname: Peschkahttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn: firstname.lastname@example.org://schemas.microsoft.com/sharepoint/2009/08/claims/userid: email@example.com://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: firstname.lastname@example.org://schemas.microsoft.com/sharepoint/2009/08/claims/identityprovider: trusted:AADhttp://schemas.microsoft.com/office/2012/01/nameidissuer: trusted:AADhttp://sharepoint.microsoft.com/claims/2009/08/isauthenticated: Truehttp://schemas.microsoft.com/sharepoint/2009/08/claims/farmid: 23883b79-ac8e-4ddb-8666-007d9ac296dbhttp://schemas.microsoft.com/office/2012/01/upn: email@example.com://schemas.microsoft.com/office/2012/01/nameid: firstname.lastname@example.org://sharepoint.microsoft.com/claims/2009/08/tokenreference: email@example.com,firstname.lastname@example.org,1301blah blah blahhttp://sharepoint.microsoft.com/claims/2012/02/claimprovidercontext: https://ds.vbtoys.com
Also note that there may be other claims coming back from ACS, but if I haven’t created a claim mapping for them then I won’t see it in SharePoint. That’s why I purposely created my PowerShell like I did – to illustrate that the claims being returned from ADFS are not getting sent all the way back to SharePoint. This is something you’ll need to think about, but actually when you consider how user rehydration works in SharePoint 2013 (for more details see http://blogs.technet.com/b/speschka/archive/2012/08/15/oauth-and-the-rehydrated-user-in-sharepoint-2013-how-d-they-do-that-and-what-do-i-need-to-know.aspx) this is not necessarily a bad thing.
At this point SharePoint is pretty much ready to go – there are just a few more steps that you should be able to do without step by step instructions:
Here’s what the whole process looks like to log into the site using ACS, AAD and ADFS:
I hit the site and get redirected to ACS, where it asks me to select the IdP I want to use:
I get redirected to my AAD tenant, where I provide the domain credentials I want to use; since I’m signing in using an account in a domain that is configured for SSO it automatically redirects me to sign in at the ADFS site I’ve configured:
I get prompted by the ADFS server I configured for DreamSwirls.com to enter my credentials:
After I authenticate I get bounced, bounced, bounced all the way back to my SharePoint site. Here you can see the home page of my site and all of the claims that came back with me (provided by my SharePoint Claims Enumeration web part I updated for SharePoint 2013 at http://blogs.technet.com/b/speschka/archive/2012/09/07/important-change-for-custom-claims-providers-in-sharepoint-2013-and-refresh-of-some-favorite-claims-tools.aspx):
There you go – that’s your end to end configuring SharePoint 2013 with Azure Active Directory and ACS. In Part 2 of this series (http://blogs.technet.com/b/speschka/archive/2013/05/12/integrating-sharepoint-2013-with-azure-active-directory-part-2-the-custom-claims-provider.aspx) I will write a post about using the Graph API on top of AAD in a custom claims provider for SharePoint.
This is a great article. Thanks for sharing. I am wondering whether it is possible to do the integration of sharepoint 2013 with AAD by skipping the Step 5 of your article. my goal here is to store users in AAD only. You created an AD tenant called DreamSwirls, so you have dreamswirls.onmicrosoft.com domain added by default. if you add a user called email@example.com using Azure management portal will you be able to login to sharepoint server with that user?
Hey Santanu, that is actually a very interesting question! Thank you for asking that, it made me just go test it out and I'm happy to report that it does work - you can use the accounts that you've created up in the cloud, the accounts from your on-premise AD, or both. So in my case, I was able to add the firstname.lastname@example.org account to a SharePoint group, and then I was able to log into the SharePoint site using those credentials.
Thank you for your quick response and I am glad to know that it worked for you. So I followed all the steps except Step 5 (Set up Directory Sync and SSO with your AAD Tenant). Now if I try to login I am getting a dropdown to choose from windows login or AAD. If I choose AAD it shows me a list of providers (Live ID, Google and my custom provider etc.). I am choosing my custom provider and it is redirecting to login page. If I login after few redirections it is prompting me with login choice dropdown again. I tried few times but it is going in loops
Then I tried to open the login page url directly (got the url from Login Page Integration section of Windows Azure Access Control Service portal). After login I am getting the following error
Exception Details: System.InvalidOperationException: Operation is not valid due to the current state of the object.
Do you have any idea what I am doing wrong here? Do you think I have to go through Directory Sync and enabling SSO steps?
Currently I am working with an Azure VM (Windows 2012 Server, AD installed, SQL 2012 and SharePoint 2013 everything I installed in one machine) for test purposes.
I am new to SSO, so please excuse my ignorance.
Thanks & regards,
Hey Santanu -
For the looping issue, I had the same problem and just figured out what was happening. The FedAuth cookie that the SharePoint STS is setting before redirecting you to your SP app is expiring. This is happening because the cookie lifetime has exceeded the lifetime of the token issued by ACS, so it's redirecting you to get a new SAML token from ACS immediately. I found that the default lifetime for the SharePoint Relying Party in ACS and the STS token cache lifetime is 10 minutes. You can raise the SAML token lifetime in ACS on the SharePoint Relying Party trust to something higher (I used 900 seconds) so that the FedAuth cookie cache is lower than the SAML token lifetime.
I love your feedback on skipping step 5. This begs another question to me. Can you skip on premises AD all together for an on premises SharePoint install? For my case, I'd like to do it for my development lab since Azure AD Services are free and it would save me waiting for my ad server to boot before starting my SharePoint Servers.
First, thanks for all the post and information you put out on SharePoint! I was wondering if is possible to not have an SSL endpoint on the SharePoint (RP) side using Windows Azure AD. I'm thinking it is not, but just want to be sure.
Are you going to do a similar blog on WAAD and SharePoint Online ?
I have an installation of a single Azure VM combined with AAD/ACS, so no on-premise components. Like Santanu above my application loops between login and accesscontrol but I am every time returned to the username/password prompt after maybe 7-8 forwards.
I followed the steps above, except #5
In the VM's event log I get errors like: An exception occurred when trying to issue security token: The trusted login provider did not supply a token accepted by this farm..
Another interesting fact is identifier claim is http://schemas.microsoft.com/ws/2008/05/identity/claims/upn whereas now WAAD provides UPN as http://schemas.microsoft.com/ws/2005/05/identity/claims/upn" so you have create new mapping in ACS.
Did any of you, who implemented Live or Google account integration using ACS with SharePoint 2013 got any search related issue? I am using Google Account. Normal browsing works fine for me. But search does not get any result for Google user whereas NTLM user gets result with same level of permission. I am not using any custom claims provider and given permission to All Users (Google Account) read permission on Site Collection.