Question

everyone.

What does 'Expiration time buffer' mean? Let me explain this to you.

In my Azure Cloud service project, there is only one Web Role. And I integrated the ACS namespace enabled with some identity provider. And the identity provider will issue an token. Anyhow, there will be a SessionSecurityToken instance. And my web role will handle its expiration.

Here is the sample code,

void SessionAuthenticationModule_SessionSecurityTokenReceived(object sender, SessionSecurityTokenReceivedEventArgs e)
    {
        Trace.TraceInformation("SessionAuthentication_SessionSecurityTokenReceived event");
        SessionSecurityToken sessionToken = e.SessionToken;            
        if (sessionToken.ValidTo < DateTime.UtcNow)
        {
            Trace.TraceInformation("SessionSecurityToken with token expiration time {0} expired at {1}. Its key expiration time is {2}",
                sessionToken.ValidTo,
                DateTime.UtcNow,
                sessionToken.KeyExpirationTime);
            Response.Write("{\"message\":\"token timeout\"}");
        }
    }   

However, not each time when sessionToken.ValidTo less than DateTime.UtcNow will trigger the token expiration exception.

Message string  SessionSecurityToken with token expiration time 06/13/2013 09:12:31 expired at 06/13/2013 09:12:37. Its key expiration time is 06/13/2013 09:12:31; TraceSource 'w3wp.exe' event

Message string  SessionSecurityToken with token expiration time 06/13/2013 09:12:31 expired at 06/13/2013 09:14:37. Its key expiration time is 06/13/2013 09:12:31; TraceSource 'w3wp.exe' event

Message string  SessionSecurityToken with token expiration time 06/13/2013 09:12:31 expired at 06/13/2013 09:16:37. Its key expiration time is 06/13/2013 09:12:31; TraceSource 'w3wp.exe' event

Message string  SessionSecurityToken with token expiration time 06/13/2013 09:12:31 expired at 06/13/2013 09:35:32. Its key expiration time is 06/13/2013 09:12:31; TraceSource 'w3wp.exe' event

And only the last time checking will trigger the exception, like this.

    Message string  <TraceSource>System.IdentityModel</TraceSource>
<Object>&lt;TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error"&gt;&lt;TraceIdentifier&gt;http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.ThrowingException.aspx&lt;/TraceIdentifier&gt;&lt;Description&gt;Throwing an exception.&lt;/Description&gt;&lt;AppDomain&gt;/LM/W3SVC/1273337584/ROOT-1-130155861607927929&lt;/AppDomain&gt;&lt;Exception&gt;&lt;ExceptionType&gt;System.IdentityModel.Tokens.SecurityTokenExpiredException, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;/ExceptionType&gt;&lt;Message&gt;ID4255: The SecurityToken is rejected because the validation time is out of range.
ValidTo: '6/13/2013 9:12:31 AM'
ValidFrom: '6/13/2013 9:02:32 AM'
Current time: '6/13/2013 9:35:32 AM'&lt;/Message&gt;&lt;StackTrace&gt;   at System.IdentityModel.Tokens.SessionSecurityTokenHandler.ValidateSession(SessionSecurityToken securityToken)
   at System.IdentityModel.Tokens.SessionSecurityTokenHandler.ValidateToken(SecurityToken token)
   at System.IdentityModel.Services.SessionAuthenticationModule.ValidateSessionToken(SessionSecurityToken sessionSecurityToken)
   at System.IdentityModel.Services.SessionAuthenticationModule.SetPrincipalFromSessionToken(SessionSecurityToken sessionSecurityToken)
   at System.IdentityModel.Services.SessionAuthenticationModule.AuthenticateSessionSecurityToken(SessionSecurityToken sessionToken, Boolean writeCookie)
   at System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs)
   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp;amp;amp; completedSynchronously)
   at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
   at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
   at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
&lt;/StackTrace&gt;&lt;ExceptionString&gt;System.IdentityModel.Tokens.SecurityTokenExpiredException: ID4255: The SecurityToken is rejected because the validation time is out of range.
ValidTo: '6/13/2013 9:12:31 AM'
ValidFrom: '6/13/2013 9:02:32 AM'
Current time: '6/13/2013 9:35:32 AM'&lt;/ExceptionString&gt;&lt;/Exception&gt;&lt;/TraceRecord&gt;</Object>

So can anyone explain this behavior? What's the problem? How to avoid this?

Thanks.

Arthur

Was it helpful?

Solution

You can override the default behavior of the SessionAuthenticationModule by setting your own timeout. I actually ran into an issue of needing to implement this to get around a 2 min timeout window of the SAML Token being issued by the Identity Provider (non-Azure) I was connecting to.

You can do this by either subclassing the SessionAuthenticationModule or handling the SessionSecurityTokenReceived event within the Global.asax.

Here's an example borrowed from the "Programming Windows Identity Foundation" book by Vittorio Bertocci that make the expiration work on a 2 minute rolling window. Although you'll have to change the namespaces to "System.IdentityModel" since they've changed when Windows Identity Foundation was added to the .NET Framework 4.5.

<%@ Application Language=”C#” %>
<%@ Import Namespace=”Microsoft.IdentityModel.Web” %>
<%@ Import Namespace=”Microsoft.IdentityModel.Tokens” %>
<script runat=”server”>
    void SessionAuthenticationModule_SessionSecurityTokenReceived
        (object sender, SessionSecurityTokenReceivedEventArgs e)
    {
        DateTime now = DateTime.UtcNow;
        DateTime validFrom = e.SessionToken.ValidFrom;
        DateTime validTo = e.SessionToken.ValidTo;
        double halfSpan = (validTo – validFrom).TotalMinutes / 2;
        if ( validFrom.AddMinutes( halfSpan ) < now && now < validTo )
        {
            SessionAuthenticationModule sam = sender as SessionAuthenticationModule;
            e.SessionToken = sam.CreateSessionSecurityToken(
                    e.SessionToken.ClaimsPrincipal,
                    e.SessionToken.Context,
                    now, now.AddMinutes(2), e.SessionToken.IsPersistent);
            e.ReissueCookie = true;
        }
    }     
//... 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top