3

I have an existing MVC4 app (.NET 4.5) using FormsAuthentication that I'm looking to switch to using SessionAuthenticationModule so that I can get a Claims aware a identity for both an easy of additional data to the identoty and as a first step to eventually migrating to performing authentication via WIF (Windows Identity Foundation) with an STS (Security Token Service) service like ADFS (Active Directory Federation Services), but that's all later down the road.

My question is, what determines the timeout when a user is authenticated using SessionAuthenticationModule?

I used this page to get my authentication working, and it seems to work fine. Basically my authentication looks like this.

Snippet from my Login action method

var personId = securityService.AuthenticateUser(model.Login, model.Password);

if (!personId.IsEmpty())
{
    authenticationService.SignIn(personId, model.RememberMe);
    if (Url.IsLocalUrl(model.ReturnUrl))
        return Redirect(model.ReturnUrl);
    else
        return RedirectToAction("Index", "Home");
}

AuthenticationService.SignIn()

public void SignIn(Guid personId, bool createPersistentCookie)
{
    var login = securityService.GetLoginByPersonId(personId);
    if (String.IsNullOrEmpty(login.Name)) throw new ArgumentException("Value cannot be null or empty.", "userName");

    var claims = LoadClaimsForUser(login.Name);
    var identity = new ClaimsIdentity(claims, "Forms");
    var claimsPrincipal = new ClaimsPrincipal(identity);
    var token = new SessionSecurityToken(claimsPrincipal, ".CookieName", DateTime.UtcNow, DateTime.UtcNow.AddMinutes(30)) { IsPersistent = createPersistentCookie };
    var sam = FederatedAuthentication.SessionAuthenticationModule;
    sam.WriteSessionTokenToCookie(token);
}

AuthenticationService.LoadClaimsForUser()

private IEnumerable<Claim> LoadClaimsForUser(string userName)
{
    var person = securityService.GetPersonByLoginName(userName);
    if (person == null)
        return null;

    var claims = new List<Claim>();
    claims.Add(new Claim(ClaimTypes.NameIdentifier, person.PersonId.ToString()));
    claims.Add(new Claim(ClaimTypes.Name, userName));
    /* .... etc..... */
}

But there is the only concern I had with this is that I want to retain the behavior of sliding expiration so the user is not prompted to re-login when their login expires, but upon working on this problem I noticed that I can't find out what determines how long they stay logged in at all. I've set the session timeout, forms timeout and the validTo parameter on the SessionSecurityToken constructor to 1 minute, but even after that elapses, I'm still able to access the site. The cookie appears in the browser with an expiry date of "Session", which I'm not sure why but even if the cookie is valid for the session shouldn't the token, identity or whatever you want to call it expire after 1 minute and force the user to log back in?

Nick Albrecht
  • 16,607
  • 10
  • 66
  • 101

1 Answers1

3

I had similar issues once, here is my question containing my approach to invalidate cookies upon token expiration

How to set the timeout properly when federating with the ADFS 2.0

Adding a bit of different logic gives you sliding expiration

http://brockallen.com/2013/02/17/sliding-sessions-in-wif-with-the-session-authentication-module-sam-and-thinktecture-identitymodel/

web.config - Setting MaxClockSkew

<system.identityModel>
  <identityConfiguration>
    <securityTokenHandlers>
      <securityTokenHandlerConfiguration maximumClockSkew="0">
        </securityTokenHandlerConfiguration>
    </securityTokenHandlers>
  </identityConfiguration>
</system.identityModel>
Community
  • 1
  • 1
Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
  • That's actually very close to what I ended up doing for the sliding expiration but I commented it all out when I noticed it didn't matter if I renewed a session token that wasn't honored in the first place. And you're right I COULD manually expire the token, but it really makes me wonder what's the point of validFrom and validTo on the token if they are not honored, and what **is** causing it to request my credentials again after a while if it's none of the timeouts I set? – Nick Albrecht May 14 '13 at 20:02
  • Could you try to set up the expiration time for 5 minutes or more and repeat the test? Wif has the clock skew of 5 minutes and if I remeber correctly, automatic expiration works correctly if the token is valid for at least 5 minutes. – Wiktor Zychla May 14 '13 at 20:14
  • Yeah that worked. Once I set the max clock skew to 0 it worked exactly as I expected. Added the path to your answer. Thanks a lot! In a distributed environment, the clock skew is probably useful but in my case it's all on one system so I don't need it. – Nick Albrecht May 14 '13 at 22:42