10

We've been setting up a SharePoint 2013 farm in a lab environment here and have hit a very odd issue with Claims authentication via ADFS. The issue is when a user connects to the SharePoint site they are appropriately redirected to the ADFS host, and after a successful sign in they are redirected back to SharePoint. That all appears to work correctly. The strange part is when they hit the SharePoint site it immediately redirects them back to the ADFS provider, who then bounces them back to SharePoint and back and forth until ADFS throws an error for too many requests within one minute.

We've followed the same configuration that has been successful for us a number of times in SharePoint 2010 and on one other SharePoint 2013 farm. We've tried two different ADFS providers with the same result. We've rebuilt the SharePoint server no fewer than 4 times all the way from a reformat of the drive and a complete re-install, with no change.

My question is: what could be causing this issue and what did we miss in the configuration?

The SharePoint Server is a VM with 12 GB of RAM and 4 Processor Cores - more than enough for a development environment methinks. The ADFS provider is set to up with the normal [sharepointhost]/_trust/ endpoint and we are sending both email and role claims, with email as the identifier. Again, this set up has worked on a number of other SharePoint servers for us; but for some reason this one is unhappy with it.

I've been up and down the ULS logs and these lines are what I see most often during this logon failure loop that I think are key:

STS Call Claims Saml: Successfully requested sign-in claim identity on behalf of user '05.t|sts.infotekka.test|jim@infotekka.test'.
...
Non-OAuth request. IsAuthenticated=True, UserIdentityName=05.t|sts.infotekka.test|jim@infotekka.test, ClaimsCount=16
...
Token Cache: Failed to get token from distributed cache for '05.t|sts.infotekka.test|jim@infotekka.test'.(This is expected during the process warm up or if data cache Initialization is getting done by some other thread).
Token Cache: Reverting to local cache to get the token for '05.t|sts.infotekka.test|jim@infotekka.test'.
security token '05.t|sts.infotekka.test|jim@infotekka.testf4d5e248-8f8d-4cdd-88f6-3e76b107db98_Internet' is found in the local cache, but it is expired. Returing Null..
Non-OAuth request. IsAuthenticated=False, UserIdentityName=, ClaimsCount=0

It looks to me like the login is successful, then when the next request for authorization comes SharePoint looks in the cache and can't find the user, then it tries the local cache and fails again, then it gives up and returns null - which kicks off another request to ADFS for an updated identity. This repeats until ADFS halts the process.

6

The solution: the clock was wrong.

After a great deal of debugging using what @Nikhil provided as a guide, I eventually found the root cause of my expiring token issue: the clock on the SharePoint server was exactly one hour ahead of the clock on the ADFS server. The time zones were set wrong as well, so visually the clocks looked right, but the UTC time was one hour off.

Consider this scenario:

  1. ADFS issues a token (default lifetime of 60 minutes) to SharePoint at 10:00 AM Mountain Time and stamps the token with that time.
  2. SharePoint receives token and checks its clock, which reads 10:00 AM Pacific Time (aka 11:00 AM Mountain Time). Compares that time to the time that the token was issued and sees that the token has entered the expiration window (the token is only valid for 60 minutes and when there are less than 10 minutes left in the lifetime SharePoint considers it expired). SharePoint rejects the token and asks for a new one, and we enter the cycle that eventually leads to a thrown exception from ADFS because of too many requests within a few seconds.

While working through this I used a couple of simple PowerShell commands that gave me a lot of information. And I should specify that in order to solve this issue I did not have to make any changes to any configuration in either SharePoint or ADFS. I only had to change my clock. And hang my head in shame.

Useful commands:

Get-SPSecurityTokenServiceConfig (SharePoint 2013 Application Server): Gives you all of the details about the Security Token Service on your SharePoint farm. Including things such as token cache expiration windows (LogonTokenCacheExpirationWindow). Any changes you make to the properties can be saved by using the .Update() method.
Get-ADFSRelyingPartyTrust -Name "My RP Name" (ADFS Server): Provides details about the Relying Party Trust that you created for your SharePoint server. Key information here is the TokenLifetime property. Saving changes to this isn't as easy; instead us Set-ADFSRelyingPartyTrust -TargetName "My RP Name" -[PropertyName] [new value]

I learned two important lessons in this process:

  1. The token lifetime is determined by the Relying Party Trust in ADFS, and is stamped with the local time of that server before being sent to SharePoint. SharePoint is in charge of determining when it feels that the token has expired (based on the LogonTokenCacheExpirationWindow property). Both of these properties can be changed but unless you have a very specific scenario, there is likely no need. Default values work fine.
  2. Step one with any kind of security troubleshooting is to check the bloody clock!

Helpful resources:

http://msdn.microsoft.com/en-us/library/hh446526.aspx
http://msdn.microsoft.com/en-us/library/hh147183(v=office.14).aspx
http://iamprogrammerdotnet.blogspot.com/2012/07/same-client-browser-session-has-made-6.html

3
+100

LogonTokenCacheExpirationWindow :Check the event viewer of ADFS and check if there is any exception like mentioned below.

Microsoft.IdentityServer.Web.InvalidRequestException: MSIS7042: The same client browser session has made '6' requests in the last '11' seconds. Contact your administrator for details.
   at Microsoft.IdentityServer.Web.FederationPassiveAuthentication.UpdateLoopDetectionCookie()
   at Microsoft.IdentityServer.Web.FederationPassiveAuthentication.SendSignInResponse(MSISSignInResponse response)

That’s because the default LogonTokenCacheExpirationWindow for the SharePoint STS is 10 minutes. The relying party by default it sets the token lifetime in ADFS to be 2 minutes, so as soon as it authenticated it knew the cookie was good for less time than the LogonTokenCacheExpirationWindow value. Therefore it goes back to ADFS to authenticate again. And so it goes , back and forth. So I needed to change the LogonTokenCacheExpirationWindow to be less than the SAML TokenLifetime.

The solution is PowerShell Script:

sts = Get-SPSecurityTokenServiceConfig
$sts.LogonTokenCacheExpirationWindow = (New-TimeSpan –minutes 1)
$sts.Update()
iisreset

OR There might be issue with the Sliding session , http://msdn.microsoft.com/en-us/library/hh446526.aspx

OR
Check the web.config if everything is configured correctly .See if the SSL configuration is configured correctly . Check if the Cookies ,session ,cache are cleared properly , these are the typical scenarios where this issues occurs. Most important check if the powershell script ran is successful to establish trust between AD and SP.

  • Thank you for responding. Setting the LogonTokenCacheExpirationWindow does allow the user to sign in, however it does not solve the root problem; which is the token is nearly immediately expired as soon as it is issued. When I applied your solution above SharePoint accepts the login and allows the site to load for the user but then makes another round trip request to the ADFS server for every request after that. This is clearly not going to work in a production environment. Do you know why the token is expiring so quickly, and what I can change to correct that? – Infotekka Nov 9 '13 at 22:59
  • Make sure the LogonTokenCacheExpirationWindow is small than the WindowsTokenLifetTime, otherwise the authentication code will go back to AD to authenticate again. And so it goes, back and forth. Powershell : $mysts = Get-SPSecurityTokenServiceConfig $mysts.WindowsTokenLifetime = (New-TimeSpan -Minutes 2) $mysts.Update() – Nikhil J Nov 11 '13 at 15:49
  • Default (and current) setting for the WindowsTokenLifetime on my STS is 10:00:00 (10 hours). Will changing that span to two minutes help? Again though: if I have a token lifetime of two minutes, and an expiration window of one minute, won't that then mean the browser has to go back to ADFS every minute to get a new token? That seems like it would be tough on the end users if their browser is constantly redirecting back to ADFS every 60 seconds. – Infotekka Nov 11 '13 at 16:29
  • Set it to hign value , that should prevent the user to get timed out . Did you try and confirming the behavior ? Also clear the "SessionCookies" . $sts = Get-SPSecurityTokenServiceConfig $sts.UseSessionCookies = $true $sts.Update() iisreset – Nikhil J Nov 11 '13 at 16:33
  • 1
    OK, after much debugging using what you provided as a guidepost I found that (embarrassingly) the clock on the SharePoint server was exactly one hour ahead of the clock on the ADFS server. Clock fixed. Problem solved. I appreciate your help. – Infotekka Nov 11 '13 at 17:15
0

I apply the chance on the LogonTokenCacheExpirationWindow, and the error gone from the ULS

$ap = Get-SPSecurityTokenServiceConfig
$ap.LogonTokenCacheExpirationWindow = (New-TimeSpan -minutes 2)
$ap.Update()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.