Figured I'd put this out here from my blog, maybe it will help someone else out, especially the exporting user profile photos at the bottom...
-Jonathan

SharePoint Server 2010 + ADFS + Claims + Google Apps, Oh My!

June 18, 2013

Introduction

First off if you’re planning on doing this read the entire article especially the Known Issues section at the bottom. Second; do this on a test or staging farm…

So here’s the scenario:  You have a SharePoint 2010 Farm that is running Windows Authentication, you want to Migrate to Claims Based Authentication so you can have users log in with Google Accounts (could be Facebook or any other Federated Identity Provider), but we’re using Google in this example.

Background

Most of the ideas, concepts in this article are not my own. I found them when researching how to implement this in our farm. Figured I’d do a write up based on what I ran into when putting all of those great sources of information into practice on a real live farm, and a lessons learned all in one place and maybe it would save some one about 14 days worth of searching Google and at least 2 calls with Microsoft Tech support. :)

You need to understand a bit about how SharePoint talks federation. SharePoint 2010 only speaks WS-Federation style tokens, it does not speak OAuth like Google does (worth noting that SharePoint 2013 does speak OAuth), so we use AuthBridge as a “translator”. You may be able to do the translation in ADFS with a Claims Transform but I’m not a guru on this and AuthBridge is already here and works.  MSDN has a lot of info on this and I’m not going to do a deep dive into what Claims are in this article. If you want to know more about Claims + SharePoint + ADFS There are several spots to check:  TechNet has a good end to end article for ADFS + SharePoint

Our Farm Setup:

1x SharePoint 2010 WFE with the June 2012 CU October 2012 CU applied, ours also has the User Profile Service running and syncing and I’ll touch on converting that over, and an issue we had.

1x ADFS 2.0 Server that also has AuthBridge running on it.

… and of course SQL Server…

How to do it:

Install ADFS 2.0 & AuthBridge on your “Federation” Server

After you have your Windows 2008 R2 Server up and running install your SSL Cert on it. FYI If it is a wildcard Cert there is a Feature in W2K8R2 that won’t allow you to use the ssl cert on multiple Web Applications unless the friendly name starts with * so to get this working open up MMC and add the Certificates snap-in for the COMPUTER ACCOUNT -> LOCAL COMPUTER (assuming you’ve rdp’d into your server), Right click and go to properties -> General and you will see Friendly Name -> Put an asterisk as the first character and OK out of the boxes. (Article with screen shots)

Get you a Windows 2008 R2 server that has IIS installed, download ADFS 2.0 and install it.
*** TIP ***You may want to have the ADFS 2.0 DATABASE running on a SQL Server, ensure you research this prior to running the wizard. This will give you the ability to build some redundancy and futureproof your deployment. The default install for ADFS 2.0 will use the “Windows Internal Database” (I have no clue what that is but it’s not SQL Server)
Once  you have ADFS installed create another web application that is SSL Secured for AuthBridge.

Unzip and install / setup the AuthBridge Web application  See the “Deploy it locally on your own” section of the AuthBridge link.

One thing you need to decide here is how you’ll be encrypting your certificates. Most commercial SSL Certificates come with a private key, that is what I would recommend instead of having to manage another certificate assuming you’re using at least a 128-bit Cert.

You’ll need to get both AuthBridge and ADFS setup in DNS, and ensure they are working before moving to the next step.

Migrating SharePoint

**TEST THIS IN A STAGING OR DEVELOPMENT ENVIRONMENT BEFORE PROCEEDING!!! Make sure you have a good backup**   I’m not responsible if you hose your farm

We’ll be running/editing/testing a few PowerShell scripts here, so if you have the PowerShell IDE installed that will help you, as long as it’s version 2.0 and not 3.0 ;)

That being said Sharepoint 2010 (at least at the time I’m writing this) doesn’t not play well with PowerShell v3.0 aka MS KB2506146. Save your self a headache and make sure this is NOT installed on your WFE. If it is take it off. This will give you Odd PowerShell errors.

How To Steps:

Disable the My Site Clean Up Timer Job (this is what deletes user profiles and runs every hour by default)  More Info Read here at the bottom of the post where it says Avoid My Sites Deletion it also apples to user profiles.

Do not enable the job until we’re finished AND we do testing to see which profiles will be deleted when the job is enabled, if you don’t wait you WILL LOOSE DATA.

Next Step is to disable the user profile sync schedule, in addition to that I recommend you disable the search indexing, what were doing is going to require some CPU and RAM so I recommend not crawling.

Next you need to add your full Cert Chain. What this means is your encryption certificate (most likely it’s your SSL Certificate)  you picked when setting up ADFS is usually from a 3rd party, that third party got trusted from a root certificate vendor for example VeriSign trusts Thawte and Thawte trusts Google and created Google’s SSL CERT. Each one of these must be added individually, so you will need to save them individually and add them into Central Admin  -> Security Manage Trust (add each one) or you can do it via power shell

1
2
3
Add-PSSnapin Microsoft.SharePoint.PowerShell
$root = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("c:\CmyCert.cer")
New-SPTrustedRootAuthority -Name "My Certs Friendly Name" -Certificate $root

The next step is to clear the configuration cache More Info 

You do this by

1) disabling the SharePoint timer job (Services.msc)
2) Navigate in Windows Explorer to %SystemDrive%\ProgramData\Microsoft\SharePoint\Config\
3) You will see several folders with GUID names, do not delete them, figure out which one has all of the XML Files, and one CACHE.ini, delete all of the XML FILES, Do NOT Delete the cache.ini or the folder.
4) Edit cache.ini ensure the only text in the file is the number 1, and save

Now we need to map our claims, by this I mean what ADFS is going to send to SharePoint. You set these up on ADFS after you set up the Relaying Party (RP) which is SharePoint, you should have setup some Claim Rules. Now we map those in SharePoint via PowerShell:

1
2
3
4
5
6
7
8
9
10
11
12
Add-PSSnapin Microsoft.SharePoint.PowerShell
$map = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" -IncomingClaimTypeDisplayName "EmailAddress" -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/givenname" -IncomingClaimTypeDisplayName "GivenName" -SameAsIncoming
$map4 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" -IncomingClaimTypeDisplayName "SurName" -SameAsIncoming
$map5 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname" -IncomingClaimTypeDisplayName "windowsaccountname" -SameAsIncoming
$map6 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid" -IncomingClaimTypeDisplayName "GroupsId" -SameAsIncoming
$map7 = New-SPClaimTypeMapping "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" -IncomingClaimTypeDisplayName "Account ID" –SameAsIncoming
$realm = "urn:seo:SharePoint"
$ap = New-SPTrustedIdentityTokenIssuer -Name "My ADFS" -Description "SharePoint secured by ADFS from mydomain.com" -realm $realm -ClaimsMappings $map,$map2,$map3,$map4,$map5,$map6,$map7 -SignInUrl https://adfs.mydomain.com/adfs/ls -IdentifierClaim "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
$cert=New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("C:\myCertificate.cer")
Set-SPTrustedIdentityTokenIssuer -Identity $ap -ImportTrustCertificate $cert

This creates a Trusted Identity Token Issuer that we can use in SharePoint.

Now we need to convert our web apps over to claims ( don’t convert Central Admin)

We’ll use PowerShell to do this, I recommend running this script in sections so the first 4 lines, then the next 7 lines then the last two lines individually, that way if you get an error you’ll know where you’re at, and some of these can take a few to run especially if you have a lot of users.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Add-PSSnapin Microsoft.SharePoint.PowerShell
$App = get-spwebapplication "https://sharepoint.domain.com/"
$App.UseClaimsAuthentication = $true
$App.Update()
 
$account = "domain\user" #FARM ADMIN ACCOUNT
$account = (New-SPClaimsPrincipal -identity $account -identitytype 1).ToEncodedString()
$zp = $App.ZonePolicies("Default")
$p = $zp.Add($account,"PSPolicy")
$fc=$App.PolicyRoles.GetSpecialRole("FullControl")
$p.PolicyRoleBindings.Add($fc)
$App.Update()
 
$app.MigrateUsers($true)
 
$App.ProvisionGlobally()

Run this script for EACH WEB APP (Except Central admin) Make sure you DO run it for the MySites Host, change line 2 above to the URI for the web app.

After you’re done running this script enable the SharePoint Timer Job we stopped when we cleared the configuration cache, this will cause the configuration cache to re-populate.

In Central admin go to each one of your web applications and enable your new Claims Based Authentication Method.
a. Central Admin – >Manage Web Applications – > (Click to select web app) -> Authentication Providers Button -> Click Zone (Should be default) – > Check Trusted Identity Provider -> Check friendly name of ADFS Provider from 2 steps ago ex: “My ADFS”
b. DO NOT remove Windows Authentication at this time
c. Click Save and Wait, it takes a while and you will second guess weither or not you clicked save….
d. X Out of the Authentication Providers Screen after the save.

Next we need to fix the portal super reader and super user accounts, these accounts should already exist in AD.  If they don’t check MSDN on why you need them (trust me you do) and create them

1
2
3
4
5
$wa = Get-SpWebApplication "https://SharePoint.Domain.org/"
$wa.Properties["portalsuperuseraccount"] = "i:05.t|my adfs|sp_superuser@domain.org"
$wa.Properties["portalsuperreaderaccount"] = "i:05.t|my adfs|sp_superreader@domain.org"
$wa.Update()
#run the above for each web app

After you run that for each web app ensure they have the proper permissions, most likely they will not,

Central admin -> Manage Web Application -> Click on Web App-> User Policy -> Add Users -> All Zones -> Phone book and look up via MyAdfs using the account email address as the search paramater, then click on email  -> click on ok,  full control checked -> finish -> X out

Do this for both of the accounts on each web app.

The next thing to do is convert all of your windows users accounts to their claims based accounts via PowerShell. *TEST THIS SCRIPT IN A NON PRODUCTION ENVIRONMENT*

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$groupprefix = "c:0-.t|fabrikam adfs provider|"
$userprefix = "i:05.t|fabrikam adfs provider|"
$usersuffix = "@domain.org"
# Get all of the users in a web application
$users = Get-SPUser -web $url
# Loop through each of the users in the web app
foreach($user in $users)
{
# Create an array that will be used to split the user name
$a=@()
$displayname = $user.DisplayName
$userlogin = $user.UserLogin
$username = “”
if($userlogin.Contains("i:"))
#for users
{
$a = $userlogin.split('\')
$username = $userprefix + $a[1] + $usersuffix
}
 
elseif($userlogin.Contains("c:")) #for groups
{
$a = $displayname.split('\')
$username = $groupprefix + $a[1]
}
if(!$userlogin.Contains("UserName")) #leave one of the farm admins
{
Write-Host $username
Move-SPUser –Identity $user –NewAlias $username -ignoresid -Confirm:$false
}
}

After you convert all of your web applications you can convert the user profile service.

Make sure you’ve converted your MySites host.

First you need to document any custom properties, filters or non out of the box mappings for example if you’re pushing the  profile picture from SharePoint to AD, or if you have any filters applied for example UserAccountControl of Bit On Equals 2, so that disabled accounts are filtered out and removed from the user profile service. (Thanks Spence Harbar)

We’re going to delete your current sync connection for Active Directory and re-create it, so a  print screen to document your current setup is VERY IMPORTANT!

If you’re done documenting, lets proceed.

Centeral Admin -> Manage Service applications -> Manage User Profile Service -> Configure Synchronization Connections -> Hover over the Name of you AD connection Click the “Smart Tag” towards the right side and choose delete.

After the delete processes choose create a new connection, re enter your information about the connection except under authentication provider choose  ”Trusted Claims Provider Authentication” then under the Authentication provider Instance choose the friendly name of your ADFS provider that you created in PowerShell above.

After you create it before your first sync you MUST  go to the user profile service home page and choose “Manage User Properties”. Find the property called  ”Claims User Identifier”, we’re going to set this to the MAIL property from our AD Connection, so hover over it, choose the smart tag and select edit, wait for it to load then scroll down to the bottom.  Under add new mapping choose your AD Connection, mail for the attribute , and Import for the direction, click add, wait for it to process then click ok.

Why did we choose mail? Because above in our powershell script we chose the email address as our Identifying Claim for our Trusted Claims Provder

That’s all for the Claims specific mappings for the user profile service that have to be setup.

Add any other filters and other property mappings at this time. Then look at Known issues below for the profile Export fix, then run a full sync, If not you could write nulls back to active directory and blank out the photoThumbnail property.

The next few steps are critical to perform before you enable the “MySite Cleanup Timer Job” we disabled in the beginning.

We need to check and see what profiles are going to be deleted before enable that job, the best way to do this is via SQL Server Management Studio (SSMS).

Do NOT do this while the sync is running.

Open up SSMS and do a new query on your profile DB and run the following query:

Select * from userprofile_full (WITH NOLOCK) where bDeleted = 1

The profiles that show up in this query are the ones that WILL get deleted when the timer job is enabled and runs. You may have to do a few sync runs to get “good” profiles out of this. In my experience we did a Full Sync followed by an Incremental Sync, then another full sync and all of the ones marked for deletion were no longer marked.

Once you are SURE you have the user profile service working correctly (we gave it a week before we re-enabled the timer job and checked the SQL Query along with the Profiles Missing from import screen in the user profile service and ensured that only staff that were supposed to be there were indeed there) you can re-enable the timer job.

Now comes the fun part, the special group “All Authenticated Users” is no longer what it used to be so you need to check where ever you had that group at in SharePoint and re-add it’s claims based identity.

Known Issues

Search Indexing won’t work after converting to claims

So in SharePoint 2010 search will not index / crawl a Claims based AuthN site. What you have to do to fix this is Extend the site in Central Admin. Manage Web Apps and create a Windows AuthN site. On my farm I extended it in the IntRanet zone. When I extended it I didn’t use a host header we just did a very odd port number, after you extend the app then go and change your Search Service Application Content sources for your newly extended site and point the source to your odd port number site. Now the all important part, your users won’t be accessing the data this way, they’ll be accessing it via https://ClaimsBasedWebApp.domain.com not viahttps://localhost:9498 {just using this port as an example of the odd ball port number}. To fix this you need to add a Server Name Mapping, it’s on the left hand nav on the Search Service App menu. to tell the Indexer/Spider/Crawler that when it indexes content at https://localhost9498 that it needs to display links tohttps://ClaimsBasedWebApp.domain.com.

Outlook 2010 can not open task from inside Outlook.

Outlook 2010 users will not be able to approve workflow tasks with in outlook, I spent over 16 hours on the phone and in remote sessions with Microsoft Support on both the SharePoint and Outlook team, they released a hot fix and now Outlook 2010 will Authenticate to ADFS just like Outlook 2013 does. Below is the KB Article, you can download the X32 or X64 bit version of the fix from there.

KB Article 2760767

If you start having “odd errors” in the user profile service sync that you NEVER had before in production then it’s time to delete and recreate the user profile service. We started getting “multiple DN for user” saying that one user had multiple Distinguished Names in AD, this was wrong, sometimes the User Profile Service just doesn’t convert over correctly to claims.

To fix these (try it in a test environment first!) Disable the MySite Clean Up Timer Job, then delete the user profile service BUT DON’T DELETE THE DATA, so don’t check the box. Using SQL Management Studio, go and delete the SYNC DB and check the drop existing connections check box. After this re-create the User Profile Service Application, and your Sync Connection, ensure you re-do your Claims mapping for the  ”Claims User Identifier” *VERY IMPORTANT* and re-do your filters. Then do a full sync and hopefully your issues should be solved, do a few more full and incremental syncs and see if you have any other problems. (Thanks Again Spence – Ton of information about the UPA on his blog!)

User Profile Service 403 Error in the Windows Application log when Photo set to Export

First off a big high five to Sunil Yadav, Priyank Pahwa and their teams from Microsoft Support for coming up with this workaround.

The User Profile Service Application (UPA) actually authenticates to the MySites host Web Application to download the photos when you have them exported to Active Directory. When you enable claims you will start seeing 403 Access Denied Errors in the Windows Application log

The UPA can’t authenticate to ADFS / Claims

* SIDE NOTE: Apparently it can authenticate to the Internal SharePoint Windows Token to Claims Service as long as you have the October 2012 CU installed. * I have NOT tested this scenario since my farm uses ADFS, but that’s what MS Support told me while I was working on resolving this export issue.

The October 2012 CU DOES NOT fix the export issue with ADFS, however there is a work around.

Once you go to Claims you’re going to have to extend any Web application that you want to make searchable because the search indexer can’t handle claims, one that you most likely will extend is the MySites host, The UPA can also use that same extended web app to do the profile photo exports… with a little bit more effort. :)

How to make it all work:

First you need to get an EXTRA STATIC IP Address that you can assign to your server. You don’t need two NIC Cards to do this. Once you have the extra free IP Address go  the TCP/IP V4 settings on your LAN card on the MySites / UPA host (this assumes they are both on the same box).  TCP/IPv4 Properties -> Advanced button on the General tab, click add and add your extra IP address. This also assumes you are using a Static IP and not DHCP.

Next edit the hosts file  C:\Windows\System32\drivers\etc\hosts

Create an entry for you EXTRA IP and your actual MySites FQDN so if your Original (non-extended) MySites host is: https://mysites.domain.com and your EXTRA IP is 192.168.1.20

In the hosts file you would have:

192.168.1.20     mysites.domain.com

See the FQDN of your mysites host is stored in the UserProfile_Full table in the Profile_DB of SharePoint.

We want to use the Hosts file to trick FIM (ForeFront Identity Manager- this is what the actual User Profile Service is in SharePoint 2010) to go to your extended windows authentication web application and get the pictures from there.

Now that that’s done you need to extend the MySites Host Web App

Extend the MySites host web app to the IntRanet Zone using Windows Authentication (that should be the only AuthN method used on this app). Do NOT give it a host header. Make the SSL and Port settings match your MySites host and create the extend web app.

After the site is created in IIS edit the binding and change it to answer only on our EXTRA IP (192.168.1.20)

Go to Central admin and change the Alternate Access Mapping of your extended web app, you should have one under your MySites Web App for http://Servername orhttps://Servername depending on if you used SSL, change this to Http://EXTRA IP or http://EXTRA IP  so https://192.168.1.20 for our example.

Now that all of that’s done our extended web app should answer so open up Internet Explorer on the server and navigate to the extended MySites host via the EXTRA IP address that you just entered and saved in the Alternate access mapping you should get prompted for Windows Credentials.

Now you should be able to run a full sync and the 403 Error should go away

If it doesn’t then do this:

Make a backup of the web.config for the EXTENDED IIS Application (cause you’re about to edit it) look for the <Authentication> section it will most likely say something like:

1
2
3
<authentication mode="forms">
..{more stuff here}..
<authentication/>

the <authentication mode=”forms”…..> line will be different, you going to delete the 2nd two lines (so the <authentication  mode=”forms”> and the </authentication> everything in between them – should just be a few 3-4 lines, and replace the top line with this:

1
<authentication mode="Windows" />

Save and exit, and for good measure do an IISReset (never hurts) and your full sync should be up and going with photos coming into the FIM MetaVerse and out to Active Directory