WIF: Long live My Session - Session Authentication Module To Avoid STS Redirect
Issue:
We are talking about problem where the SAML Token Validity Time set via custom STS is less (5 minutes) and we want to make sure NOT to redirect user every 5 min to get new SAML token.
Default STS:
When we use out of box LocalSTS.exe to create Test STS, the default token validity time is 60 minutes. And thus chances are very less we run in to above problem. But when we use the actual business STS, which can be ADFS or custom STS provider; the token time is set at STS level and in most cases we really don't have control to increase the RECEIVED SAML token validity time. However we can still trick WIF to avoid sending user to STS.
Setup:
To achieve above task, all we have to do is write custom code for Session Authentication Module - "SessionAuthenticationModule_SessionSecurityTokenReceived" event.
Logic:
The core logic which goes inside the event handler includes:
- Reading the incoming request token (which is extracted from received cookie - initially set on first request).
- Once we get the token associated with cookie, all we have to do is get the ValidFrom and ValidTo time.
- Next we check if the ValidTo time is close to CurrentTime . If yes, we reset the ValidFrom andValidTo to higher value.
- This will help me set NEW COOKIE back to client browser and at the same time make sure that current request is not dropped nor redirected to STS.
Piece of code used:
void SessionAuthenticationModule_SessionSecurityTokenReceived(object sender, SessionSecurityTokenReceivedEventArgs e)
{
SessionAuthenticationModule mySessionModule = FederatedAuthentication.SessionAuthenticationModule;
// Get Incoming Token
SessionSecurityToken incomingToken = e.SessionToken;
// Fetch Token Validity
TimeSpan tokenValidity = incomingToken.ValidTo.Subtract(incomingToken.ValidFrom);
// Time left before the token gets expired
var timeDifference = incomingToken.ValidTo.Add(mySessionModule.FederationConfiguration.IdentityConfiguration.MaxClockSkew).Subtract(DateTime.UtcNow);
// Important to catch this, because as soon as we get close to it, we will increase the token validity
Double halfToExpiry = tokenValidity.TotalMinutes / 2;
// Time left before the token gets expired
Double timeLeft = timeDifference.TotalMinutes;
// We check if our user is more than half way to expiry time, we increase the validity and please note this will set a NEW Fed Auth cookies
if (timeLeft <= halfToExpiry)
{
e.ReissueCookie = true;
e.SessionToken =
new SessionSecurityToken(incomingToken.ClaimsPrincipal,incomingToken.Context,DateTime.UtcNow,DateTime.UtcNow.Add(tokenValidity))
{IsPersistent = incomingToken.IsPersistent,IsReferenceMode = incomingToken.IsReferenceMode};
}
}
Plugin Point:
Make sure to add "Global.asax" file to the Client application. Global.asax act as container to trigger the above event handler code.
Sample app available for download: https://1drv.ms/u/s!ArgnWb8iHXB6gpcazCM6SOTDdqyhkA
Hope this helps !
Thanks
Saurabh