Skip to main content

Cloud

Sliding Sessions with SharePoint 2010 and Claims

Back in June 2010, Vittorio Bertocci posted a method to implement sliding sessions with Windows Identity Foundation (WIF) on his blog. While the article addresses ASP.NET applications configured to use WIF, Vittorio mentions that SharePoint 2010 implements sliding sessions for Forms authentication more or less out-of-the-box. Sadly this is not the case for situations where a custom STS is used for authentication. This is a critical gap so I naturally looked for documentation on how this can be implemented. I couldn’t find any, but thankfully I’ve discovered the process is largely the same that Vittorio outlines. Of course since we’re talking about SharePoint 2010 here, there are important nuances involved, hence this article. J
Side Note: The content of Vittorio’s blog is actually found within a chapter of his excellent book. If you’re at all interested in claims and Windows Identity Foundation, you should definitely check it out. You’ll be glad you did.

Background

Before starting, you should be aware that there are actually two tokens at play here:

  1. The incoming token. This is the SAML token issued to the user by the external identity provider (STS). When this token is authenticated and a session is established, Windows Identity Foundation uses this data to generate the IClaimsPrincipal object, which represents the user within SharePoint. All SAML tokens have a defined lifetime and this determines how long the user can be in the system before needing to re-authenticate.

     

  2. The session token. This represents an authenticated session and mostly consists of data from the incoming token. It is persisted as a cookie called FedAuth and is located either on the file system or, if SharePoint is configured in session cookie mode, in the browser’s memory. Session tokens also have a defined lifetime. In SharePoint 2010, this is equal to the lifetime of the incoming token minus the value of the LogonTokenCacheExpirationWindow property (see below). The session token can be referred to as the session cookie or, in code, SessionSecurityToken.

So by taking all that into consideration, a five minute sliding session model in SharePoint 2010 claims mode could look something like this:

Be aware that implementing sliding sessions is all about manipulating the session token lifetime, not the incoming token issued by an STS. In this example, once a session token has reached half of its lifetime or more (5 minutes in this case), a new one is issued with a lifetime of 10 minutes and the process repeats as long as the user is active in SharePoint. Note that sliding sessions must live within the lifetime of the incoming token. Once the incoming token expires, the use must re-authenticate to the external STS. So in general, it’s likely these will have a longer lifetime like 8 or 10 hours.

Configuration

For starters, you’ll need a SharePoint web application configured to use an external STS. For this demonstration, I’m using the proof-of-concept Facebook STS that I discussed in a previous post. I made a minor change to the STS in the CustomSecurityTokenServiceConfiguration class so that issued SAML tokens have a default lifetime of 8 hours.

public static CustomSecurityTokenServiceConfiguration Current
{
get
{
HttpApplicationState httpAppState = HttpContext.Current.Application;
CustomSecurityTokenServiceConfiguration customConfiguration = httpAppState.Get( CustomSecurityTokenServiceConfigurationKey ) as CustomSecurityTokenServiceConfiguration;

if ( customConfiguration == null )
{
lock ( syncRoot )
{
customConfiguration = httpAppState.Get( CustomSecurityTokenServiceConfigurationKey ) as CustomSecurityTokenServiceConfiguration;
if ( customConfiguration == null )
{
customConfiguration = new CustomSecurityTokenServiceConfiguration();
httpAppState.Add( CustomSecurityTokenServiceConfigurationKey, customConfiguration );
}
}
}
customConfiguration.DefaultTokenLifetime = new System.TimeSpan(8, 0, 0);
return customConfiguration;
}
}
The next part involves adding code behind to the SharePoint web application’s global.asax file. This is where we handle the SessionSecurityTokenReceived event. In my case, the page directive looks like this:

<%@ Application Language=”C#” Inherits=”ClaimsTest.Global,ClaimsTest,Version=1.0.0.0,Culture=neutral,PublicKeyToken=c6bde9e5c7cb8ea3″%>

An excerpt of the code behind (global.asax.cs) is seen below. I’ll leave the explanation of what it does to Vittorio’s blog since there isn’t anything really new here. I’m just using the derived SPSessionAuthenticationModule class instead of the parent WIF class.
Note that you’ll need to add a project reference to Microsoft.IdentityModel (C:Program FilesReference AssembliesMicrosoftWindows Identity Foundationv3.5Microsoft.IdentityModel.dll) and Microsoft.SharePoint.IdentityModel (C:WindowsassemblyGAC_MSILMicrosoft.SharePoint.IdentityModel14.0.0.0__71e9bce111e9429cMicrosoft.SharePoint.IdentityModel.dll).

using System; using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using Microsoft.SharePoint;
using Microsoft.SharePoint.ApplicationRuntime;
using Microsoft.SharePoint.IdentityModel;
using Microsoft.IdentityModel.Web;

namespace ClaimsTest
{
public class Global : SPHttpApplication
{
public override void Init()
{
FederatedAuthentication.SessionAuthenticationModule.SessionSecurityTokenReceived += new EventHandler<SessionSecurityTokenReceivedEventArgs>(SessionAuthenticationModule_SessionSecurityTokenReceived);
base.Init();
}
void Application_Start(object sender, EventArgs e)
{
}
void SessionAuthenticationModule_SessionSecurityTokenReceived(object sender, SessionSecurityTokenReceivedEventArgs e)
{
DateTime now = DateTime.UtcNow;
DateTime validFrom = e.SessionToken.ValidFrom;
DateTime validTo = e.SessionToken.ValidTo;
if ((now < validTo) && (now > validFrom.AddMinutes((validTo.Minute – validFrom.Minute) / 2)))
{
SPSessionAuthenticationModule spsam = sender as SPSessionAuthenticationModule;
e.SessionToken = spsam.CreateSessionSecurityToken(e.SessionToken.ClaimsPrincipal, e.SessionToken.Context,
now, now.AddMinutes(1), e.SessionToken.IsPersistent);
e.ReissueCookie = true;
}
}
}
}
Next, we need to configure our web application to issue session tokens with a finite lifetime. For testing, I set this to one (1) minute by modifying the SPTokenCache handler in web.config. This can be found within the <microsoft.identityModel> section.

<add type=Microsoft.SharePoint.IdentityModel.SPTokenCache, Microsoft.SharePoint.IdentityModel, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c>
<sessionTokenRequirement lifetime=0:01/>
</add>

Lastly, I updated the LogonTokenCacheExpirationWindow setting in SharePoint. I have found that it is necessary this value be less than the session token lifetime configured above. Since we’re using sliding sessions here, this setting really isn’t necessary so I configured it to one (1) second to make sure it stays out of the way. This is done via the following PowerShell commands:

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

Note that in the above example I also enable session cookies. This is not a requirement, however.
If all goes well, you should be able to sign into SharePoint using a custom STS and maintain an active session as long as you click around every few seconds. If you (according to these settings) idle for one minute, you should find that you must re-authenticate to the custom STS to continue. Hopefully, this should get you started down the path of implementing your own sliding session model in SharePoint 2010 when using claims mode.

Thoughts on “Sliding Sessions with SharePoint 2010 and Claims”

  1. Indeed, great post! I was quite surprise that this wasn’t somehow built into SP 2010…Yesh: probably to reduce overhead. Everyone, make sure you read the entire blog…especially the part about the TWO tokens, instead of going straight to code!

  2. Bug fix:
    int timespan = System.Convert.ToInt16(WebConfigurationManager.AppSettings[“SlideTimeout”]);
    Boolean isInitialSlideSet = false;
    if ((validTo – validFrom).TotalMinutes > timespan)
    {
    isInitialSlideSet = true;
    }
    if (((now validFrom.AddMinutes((validTo – validFrom).TotalMinutes / 2))) || isInitialSlideSet)
    {
    SPSessionAuthenticationModule spsam = sender as SPSessionAuthenticationModule;
    e.SessionToken = spsam.CreateSessionSecurityToken(e.SessionToken.ClaimsPrincipal, e.SessionToken.Context,
    now, now.AddMinutes(timespan), e.SessionToken.IsPersistent);
    e.ReissueCookie = true;
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Travis Nielsen

More from this Author

Follow Us