5

I have an interesting problem with trying to keep track of expired WIF authentication sessions/cookies.

As a bit of background: the site is MVC 3, uses Windows Identity Foundation (WIF) that has a trust with an ADFS server as an STS. The entire site is protected by SSL. The STS has the token expiry set to 60 minutes.

When a user signs out manually, we just simply call the SignOut method on the FedAuth module:

FederatedAuthentication.WSFederationAuthenticationModule.SignOut(false);

This of course removes the FedAuth cookies, but here's where the problem starts. If I capture those cookies with Fiddler, I can re-present them to the site within their expiry time and still be treated as logged in.

I realise that this is being performed from a privileged position of the browser having accepted fiddler as a proxy... but the customer is worried that those auth cookies not actually being expired presents a significant security risk. They're are not convinced that SSL protects the site sufficiently, and that if an attacker could execute an MITM attack, they could use those cookies after the user thinks they have logged out.

I have explained that if they are vulnerable after log out, they are vulnerable during log in, but they don't care...

So I have looked for ways to be sure that once a user logs off, the fedauth cookies associated with that logon session are treated as expired. The WIF handlers don't seem to have a built in mechanism for tracking expired tokens, and I have not found anything else related to this.

I guess that this is in fact a wider problem -> how to detect expired cookies in general? A valid cookie is a valid cookie!

The obvious solution is to track those cookies after logout somehow, but I'd like to avoid the custom code route if possible; as a noob, a lot of the security literature says to avoid custom coding any kind of session mechanics, as you will probably get it wrong!

Is anyone aware of any standard solutions in ASP.NET to this problem?

Thanks in advance.

oolong
  • 105
  • 1
  • 8

2 Answers2

7

You don't without keeping a server-side list of the tokens recently revoked. This is why normally we rely upon an inherent expiration as well as HTTPS to prevent the token from being leaked/stolen.

Brock Allen
  • 7,385
  • 19
  • 24
  • 1
    Thanks for that @Brock Allen, that's the kind of pragmatic push-back-answer I was looking partly looking for. Would you say that your statement "This is why we normally rely upon an inherent expiration as well as https" is common practice on the web? I know that regardless of any explanation I give they will still ask me to come up with possible solutions for expired token tracking. Do you have / know of any working examples of this is ASP.NET? Left to my own devices, I would probably opt for using a dictionary to store tokens by some identifier, and then do a look up post-initial-auth... – oolong Apr 15 '14 at 23:09
  • 1
    Yes, a built-in token expiration is a way to prevent runaway access. If you want to track this, you simply build a DB of tokens and the user and the expiration. – Brock Allen Apr 16 '14 at 00:34
  • Are you able to point me to working examples of such a system? I have searched extensively for an example, but haven't found anything related in any technology. :( – oolong Apr 16 '14 at 01:46
  • 1
    No, I don't know of any samples -- in my apps I rely upon the expiration. But I wonder what you're trying to protect against? The user is the only one with the cookie (because you should be using SSL). So why are you trying to prevent a user from caching a cookie and replying it after they say they want to logout? They had access already. – Brock Allen Apr 16 '14 at 12:48
  • Thanks for your replies! It isn't the user they're worried about. They are worried that if a malicious person was able to pull off some kind of MITM attack (bearing in mind that the entire site is protected SSL), they might be able to replay the legitimate users requests (Which contain valid tokens) to do malicious damage. – oolong Apr 16 '14 at 21:32
  • As far as I know (I'm by no means an expert), replay attacks would be the only thing a successful MITM attack you could pull off with SSL protected requests. Theft of the tokens in plain text isn't possible in this scenario. Mind you elsewhere, I have also read that SSL has some sort of innate protection against replaying messages. – oolong Apr 16 '14 at 21:32
  • 3
    The point of SSL is to authenticate the server, so MITM should not be an issue. – Brock Allen Apr 18 '14 at 00:01
  • @BrockAllen Are you still relying on HTTPS/Expiration in 2018 for cookie security? Has anything changed in the last 4 years to invalidate this approach? – foldinglettuce Feb 16 '18 at 22:56
  • Look into HTTP token binding. – Brock Allen Apr 28 '18 at 21:30
1

I was tasked with a similar request by our security team. I opted to store the asp.net session id in the OWIN cookie and on each request that contained a session id in the cookie I verify it matches the active session's Id.

Store session id in the cookie (adapted from this answer) at the end of the first request that is authenticated and doesn't already have the session id in the cookie:

protected override void OnActionExecuted(ActionExecutedContext filterContext)
    { 
        base.OnActionExecuted(filterContext);

        bool authenticated = User.Identity.IsAuthenticated;

        var sessionGuid = (User as ClaimsPrincipal).FindFirst("sessionID")?.Value;

        //put the SessionID into the cookie.
        if (authenticated && string.IsNullOrEmpty(sessionGuid))
        {
            var id= Session.SessionID;

            //update the guid claim to track with the session
            var authenticationManager = HttpContext.GetOwinContext().Authentication;

            // create a new identity from the old one
            var identity = new ClaimsIdentity(User.Identity);

            // update claim value
            identity.RemoveClaim(identity.FindFirst("sessionID"));
            identity.AddClaim(new Claim("sessionID", id));

            // tell the authentication manager to use this new identity
            authenticationManager.AuthenticationResponseGrant =
                new AuthenticationResponseGrant(
                    new ClaimsPrincipal(identity),
                    new AuthenticationProperties { IsPersistent = true }
                );
        }
    } 

Then on each future request if I find a session in the cookie compare it to active session. If they don't match then logout:

protected override void OnActionExecuting( ActionExecutingContext filterContext)
    {
        var claim = (User as ClaimsPrincipal).FindFirst("sessionID")?.Value;

        //does the owin cookie have a sessionID?
        if (!string.IsNullOrEmpty(claim))
        {
            string session = Session.SessionID;

            //does it match the one stored in the session?
            if(session != claim)
            {
                //no? log the user out again..
                Session.Abandon();

                //redirect to logged out page
                this.Request.GetOwinContext().Authentication.SignOut();

                //tell them its over..
                Response.Write("Expired Session");

                Response.End();
            }
        }

        base.OnActionExecuting(filterContext);
    }
foldinglettuce
  • 522
  • 10
  • 28
  • Does this have possible unintended side effects? The lifecycle of your session is not intrinsicly linked to the lifecycle of your auth cookies, so now you have to closely manage the two in order to prevent one expiring before the other etc. – oolong Jun 26 '18 at 22:28
  • @oolong I prefer Brock's answer because it doesn't have the side effects you describe. I was unable to convince the security people that Brock's answer was good enough so I figured I'd add my solution here for posterity. – foldinglettuce Jul 06 '18 at 22:33