Here’s an interesting scenario I hadn’t experienced before: SharePoint 2013 farm doing a user profile sync with Active Directory. Security was based on Active Directory security groups managing membership and authorization controlled through SharePoint groups containing the AD groups. As users were added and removed to/from the AD groups, they weren’t seeing the change reflected in the SharePoint sites. After a crash course in claim caching, here’s what we ended up with.
First, an admittedly simplistic view of how SharePoint manages tokens:
- User browses to SharePoint site
- SharePoint checks local token store (STS) for a non-expired cached claim for that user
- If not found, STS creates a new claim by querying AD and then adds it to the cache
- If found, uses the cached claim
That covers the user, now lets look at how SharePoint syncs with AD to get group and membership info. Managed by the User Profile Sync service, SharePoint queries AD to learn about new or removed users as well as group membership. This is also controlled by a cache, and can create the scenario we ran into where AD users that were added or removed from AD groups did not have their authorization permissions updated in SharePoint.
By default, SharePoint will cache this group membership info for 24 hours. Well, we weren’t that patient. We changed it to two minutes using the following command:
stsadm.exe -o setproperty -propertyname token-timeout -propertyvalue 2
That sets the timeout to two (2) minutes. Admittedly a bit extreme, but we’ll set it back to a more reasonable timeframe when things aren’t so volatile.
So that takes care of SharePoint becoming aware of AD group permission changes, but how about user claims being updated? If SharePoint is aware of a user now being granted access through membership in an AD group, but that user obtained their claim earlier in the day before the AD group membership was changed, they will still be denied access. To change that we looked at setting the LogonTokenCacheExpirationWindow and WindowsTokenLifetime properties for the STS:
$sts = Get-SPSecurityTokenServiceConfig
$sts.FormsTokenLifetime = (New-TimeSpan -minutes 2)
$sts.WindowsTokenLifetime = (New-TimeSpan -minutes 2)
$sts.LogonTokenCacheExpirationWindow = (New-TimeSpan -minutes 1)
The above is telling the STS that claims tokens are good for one (1) minute. WindowsTokenLifetime – LogonTokenCacheExpirationWindow, so 2 – 1 = 1. I’m pretty good with math. Default for both is 10 hours.
Oh, if you happen to set a lifetime that is shorter than the expiration window, that’s a good way to block users from accessing the site. Once their existing token expires, they’ll start seeing a message “The context has expired and can no longer be used.”
In other words, don’t do that.
Now every minute STS will refresh the claim token for a user to get the latest and greatest membership info from AD. That seemed to do the trick for this scenario, and we’ll definitely adjust the values above when things aren’t so volatile, but for now we’re looking good.
Here are a couple references we used to get to this result:
http://blog.robgarrett.com/2013/05/06/sharepoint-authentication-and-session-management/ (specific to ADFS, but after being shown this through a co-worker I really started to understand lifetime and expiration dependencies)
For any security and/or IT Pro experts reading this, please comment and correct me where I’m wrong or was too vague.