Okta vs. SharePoint Server On-Premise

Okta vs. SharePoint

The Case of The Missing Manual:

Okta vs. SharePoint Server On-Premise

Dr KinleyWarmest greetings to you! Dr Kinley here again. In this chapter of Dr Kinley’s Facebook, we look at some of the configuration pitfalls with Okta and SharePoint Server in “The Case of the Missing Manual”.

A customer came to us having already embarked upon a project to migrate their SharePoint Server farm, and several thousand existing users, to Okta, the single sign-on cloud application.

If you are considering migrating to Okta for an existing SharePoint on-premise farm, you are doing something that is possibly very, very hazardous to the well-being of your SharePoint farm. You are potentially about to make a C.L.M. (Career Limiting Move).

We managed to avoid a lot of pain for our customer by filling in the gaps left by Okta.

If you are considering such an integration yourself, and haven’t started the process yet, read this first!

The Art of the Possible

Don’t let anyone – especially Okta – tell you otherwise. This is what is definitely achievable with SharePoint and Okta:

  • Existing Windows users can be migrated to Okta users
  • Existing Windows groups can be migrated to Okta groups
  • Permissions can be retained

Here’s what you can’t do:

  • Configure SharePoint services to run as Okta accounts
  • Switch off NTLM entirely

Required Reading

Before you get started, you’ll need to read these:

Missing from the Manual

There seems to be a manual missing. I’ve looked, I’ve Googled, I’ve asked. The configuration steps for SharePoint on-premise and Okta seem to not be adequately documented.

Okay, well… some of these things Okta tells you. But they don’t tell you loud enough. And they don’t tell you in nearly enough detail. Also the professional services teams at Okta don’t seem to know how to do some of these things themselves. Expect to be on your own. And expect their documentation to be out of date and full of holes.

The rest of this blog post describes some of the missing pieces of knowledge you’ll need to configure SharePoint Server on-premise and Okta without losing precious data.

#1: One SharePoint Web Application equals one Okta App equals one Realm

Create one Okta app per SharePoint web application. You get told the Realm from the Okta App. On the Sign-On tab there is a button that takes you to something that looks for all the world like a knowledge base article. Even down to the formatting and styling of the page. There is literally no clue that the strings and values on that page were uniquely generated for your app, and aren’t the generic manual pages they seem to be.

Somewhere halfway down, way below the fold, you’ll find an example piece of code like this:

$ap = Get-SPTrustedIdentityTokenIssuer "Okta"
$uri = new-object System.Uri($sharepoint_app)
$ap.ProviderRealms.Add($uri, "urn:okta:BIGNUMBERHERE")
$ap.Update()

The Realm for your specific web application is the big, red string on line 3 above. You’ll need to copy and run their block of PowerShell for each additional web application you need to support.

#2: Users need to be migrated to their Okta equivalent

If you are converting an existing SharePoint farm with Active Directory users, you need to migrate them all to Okta users.

You can migrate a user from one identity provider to another with Move-SPUser. You pass it arguments for the current user name to the target user name (e.g. DOMAIN\UserName). Because we’re dealing with claims, the current user name is likely to look like: i:[email protected], and the target would be something like: “i:0<UNICODE_CLAIM_TYPE_CHARACTER>.[email protected]”. The “.w” means Windows authentication mode, whereas the “.t” means trusted token issuer.

So, how do you find the correct value of <UNICODE_CLAIM_TYPE_CHARACTER>?

#3: Every SharePoint Farm has a different Claim Type Encoding character for Okta

SharePoint has a bunch of built-in claims that it knows of already. The built in claims encoding characters are listed on TechNet. User Principal Name, Email Address etc.  When you install an additional identity provider, such as Okta, SharePoint creates another entry for its principal claim and assigns it a unique character (unique to your farm). You can retrieve the character with the following PowerShell:

Get-SPClaimTypeEncoding | ? { $_.ClaimType -like '*Okta*' };

Putting this all together, you get:

$oktaClaimChar = Get-SPClaimTypeEncoding | 
    ? { $_.ClaimType -like '*Okta*' };

Get-SPUser -Web https://contoso.local 
   -Identity "i:[email protected]" | 
   Move-SPUser -NewAlias ("i:0" + $oktaClaimChar +
      ".[email protected]");

Important safety tips:

  1. Migrating the same user twice is bad *
  2. Migrating service accounts is bad **

* …Really bad. SharePoint deletes all instances of the original user and replaces it with a new blank one that owns nothing. You lose all permissions information about the user.

** …you’ll kill the User Profile Service stone dead, for instance.

#4: Groups need to be migrated to their Okta equivalent

The Okta engineer assigned to us didn’t seem to realise there might even be an issue with groups.

“After migrating the users, what should we do about groups?” I asked.

“Oh, I don’t think there should be a problem,” he said.

Obviously, wrong.

The next Okta engineer tried to explain that Okta only used groups to advertise your Okta apps to users, and we should replace the Active Directory groups with SharePoint groups.

“You can select the Okta groups that will be shown the SharePoint icon when they sign in. It works based on the first group you’re a member of. You need to add your Okta users to SharePoint groups.”

Also wrong.

You definitely, positively need to migrate your Active Directory groups in SharePoint to their Okta equivalent. However, there is no PowerShell cmd-let equivalent of Move-SPUser. Instead you need to do some object model work:

$f = Get-SPFarm;
$f.MigrateGroup("contoso\group name", "c:0-.t|okta|group name");

To help, here’s how you can get a list of Windows groups to migrate from a specific site collection:

$s = Get-SPSite https://contoso.local;
$s.RootWeb.SiteUsers | ? { 
	$_.IsDomainGroup -and $_.UserLogin.Contains("c:0+.w|s-1-5")
} | % { 
	$group = $_;
	$oldGroupName = $group.UserLogin;
	$newGroupName = "c:0-.t|okta|" + $group.DisplayName.ToLower();
	$f.MigrateGroup($oldGroupName, $newGroupName);
}; 

By the way, the in the “c:0-.t|okta|” prefix above, the dash character is the claim encoding type symbol for the built-in ‘role’ claim, and is not specific to Okta scenarios.

#5: Search configuration with claims Web Applications is poor

There is no satisfactory solution to this one.

SharePoint Search needs to crawl an NTLM zone. It cannot meaningfully crawl documents from a claims-only zone. If you configure Okta and NTLM on the same zone, SharePoint will prompt the user to select an authentication scheme when they sign in. If you have just migrated several thousand users to Okta, that would be a tremendous mistake. If a user chooses “Windows Account” by accident, it effectively creates them a separate user record within SharePoint that seems to have the same name as theirs but with zero permissions on anything.

SharePoint Search also needs the zone it crawls to be the one called “Default”. This is bad behaviour by design.

Why is this bad? Because when SharePoint doesn’t fully recognise the host header mapping used by the user (e.g. they type the machine name or IP address into the address bar instead of the fully qualified domain name) it pretends you accessed it via the “Default” zone. And it applies all the policy and URL-related shenanigans that come along with that decision.

Best practice in SharePoint architecture is to make the Default zone the most secure one – and the one that has the policies and authentication schemes you want people to default to. But any scenario with claims providers plus SharePoint Search turns that on its head.

The takeaway:

  • Make the Default Zone NTLM only.
  • Enable Okta on a different Zone.
  • Be consistent in those zones for all web applications you host in SharePoint.

For extra points, configure a User Policy at the web application level for each Default zone to deny read/write access to any normal Windows (NTLM) user.

#6: Okta app configuration documentation is poor

The “Group filter” setting tells Okta what group membership claims from AD should be passed to SharePoint. In other words, if I am a member of AD groups “JFDI Administrators”, “JFDI Portal Owners” and “Domain Users”, and I would like to be able to authorise access to a specific list or site based upon membership of these groups, I need to get the value of this filter right.

Some important points: It’s a ‘filter in’ rather than ‘filter out’. It’s a regular expression. So if you want *all* AD groups to be available to SharePoint, this needs to hold the value of .* and nothing else. Definitely not * or left blank. In my example above, if I only wanted to allow SharePoint to know if users are members of groups with a name starting with the letters “JFDI”, then my group filter value would need to be “JFDI.*”.

Okta Group Filter Dialog

#7: Okta is not compatible with SharePoint Publishing Site Collections

OK – as of March 2017 it is.

In November 2016 I uncovered and identified a blocking issue. I found a bug when trying to create a new site collection based upon a vendor’s site definition. Initially, Okta tried to blame the site definition developed by the vendor. Closer inspection of log files showed it was to do with activating the SharePoint Server Publishing Infrastructure feature.

Before we could persuade Okta to bother to recreate the issue themselves, I had to build a brand new farm with just Okta on it and show that any attempt to create a site collection that uses SharePoint publishing – e.g. the built-in Publishing Portal template – would fail, with a ULS entry pointing to Okta’s claim provider. At last they took the issue seriously.

We had to wait 4 months for that fix, but at least it does now work properly. Make sure you get the March 2017 update of their people picker solution.

#8: Migrate All Your SharePoint Web Applications

At the very least, you will have a web application for your content, and a web application for your My Site Host/OneDrive for Business sites. All your Windows web applications – i.e. all the ones which have users in the Active Directory domains you are migrating – and all their users – need to be migrated to Okta.

We wrote a script to iterate over:

  • All web applications
    • All site collections therein
      • All site users with a Windows account

At that innermost loop, we execute Move-SPUser. Doing it in this way ensures that no user is migrated twice; upon migration, a user is converted to Okta everywhere. This takes the user’s Windows account out of the site users collection of sites we haven’t iterated over yet.

#9: Test, Test and Test Again

I can’t stress this enough. You are about to risk serious harm to the ownership and permissions of everybody and every group across your entire farm, and all of the content that includes – sites, lists, libraries, folders and files. Everything.

You owe it to yourself to get this right:

  • Build a proof of concept environment and test the process.
  • Test all kinds of web application, including My Sites if you have them.
  • Build a carbon copy of live, and test with that.
  • Take full farm backups. Test your backups. No test equals no backup.
  • Seriously test you can restore from your backup. If you do not test your backup, you do not have a backup. You have some carbon on a disk. You have two hopes, Bob Hope and no hope… etc, etc.
  • Did I mention backups yet?

#10: Tidy-up Activities

There will probably be activities to do after the migration. Very soon after.

Here are some things that will break. Try and identify if you will be affected by any of these before you migrate.

RSS Web Parts with SharePoint Lists as data sources

You will have to replace these with something else. Maybe Content Query or Content Search web parts. Or JavaScript and REST or JSOM.

Secure Store Applications

You will see a lot of Access Denied errors. Move-SPUser does not seem to alter user information in the Secure Store. Individual and Group application memberships will need to be updated / replaced with their Okta user and group equivalents. The unattended execution (data access) accounts of Excel Services, Visio and PerformancePoint will be affected.

Reporting Services

Using SharePoint lists as OData sources? You will need to establish a Windows account to read that data from the zone you configured for NTLM.

User Profile pictures

If you’re displaying User Profile photos in search results from any web application other than the My Sites one, users will see broken images until they sign in to the My Sites domain. To avoid this you can enable cross-domain user profile pictures on each web application:

$wa = Get-SPWebApplication "https://contoso.local";
$wa.CrossDomainPhotosEnabled = $true;
$wa.Update();

If you’re unlucky enough to use a 3rd party web part to display profile images, it might not know how to honour the above setting. In that case, you’ll need to bust open your JavaScript skills. You can use JavaScript to latch on to the OnError event of the offending IMG element, and reload with the local version of the user’s photo URL: /_layouts/15/userphoto.aspx?size=M&url=<ORIGINAL_PHOTO_URL>

Here’s an example using jQuery:

$('#myContainer > img').on('error', function() {
    var url = "/_layouts/15/userphoto.aspx?size=M&url=" +
        encodeURIComponent($('#myContainer > img').attr('src'));
    $(this).attr('src', url);
});

Conclusion

If this seems all too much like hard work, that’s because it is. Retrofitting Okta to SharePoint on-premise is full of pitfalls.

Get in touch if you’d like help to plan or perform your Okta and SharePoint integration and avoid a potential disaster.