Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WIF sliding session re-authenticate

I've implemented sliding sessions in my Relying Party application, as described in Sliding Sessions for WIF 4.5. That works great as far as it goes, but there's one problem that it seems nobody talks about.

As the linked blog post points out, when the RP token expires, the next time make a request the token is re-issued from the STS. Assuming, of course, that the STS session lifetime is longer than the RP's session lifetime, which is almost certainly the case if you're implementing sliding sessions.

In any event, that completely defeats the whole point of sliding sessions.

What nobody seems to talk about is what to do when the RP session expires. What I want is, if the RP session times out (usually because somebody walked away from his desk for 10 minutes), is for my application to redirect to the STS login page where the user can re-authenticate, and then be redirected back to the page I had requested; or perhaps to the page that I was on when I made the request.

I'm almost certain that this is possible, but I have absolutely no idea how it's done.

Here's my code from global.asax:

    private const int InactivityTimeout = 5; // minutes

    void SessionAuthenticationModule_SessionSecurityTokenReceived
        (object sender, SessionSecurityTokenReceivedEventArgs e)
    {
        var now = DateTime.UtcNow;
        var validFrom = e.SessionToken.ValidFrom;
        var validTo = e.SessionToken.ValidTo;
        double halfSpan = (validTo - validFrom).TotalMinutes/2;
        if (validFrom.AddMinutes(halfSpan) < now && now < validTo)
        {
            // add more time
            var sam = sender as SessionAuthenticationModule;

            e.SessionToken = sam.CreateSessionSecurityToken(
                e.SessionToken.ClaimsPrincipal,
                e.SessionToken.Context,
                now,
                now.AddMinutes(InactivityTimeout),
                e.SessionToken.IsPersistent);
            e.ReissueCookie = true;
        }
        else
        {
            // re-authenticate with STS
        }
    }

My questions:

  1. Is the else clause the proper place to put the re-authentication logic?
  2. If so, please provide an example, 'cause I have no idea.
  3. If the answer to #1 is no, then is there a separate event I need to subscribe to that will tell me "Hey, your session security token has expired!"?
like image 446
Jim Mischel Avatar asked Sep 05 '13 16:09

Jim Mischel


1 Answers

I'd recommend you sync the session lifetimes on the STS and the RP(s).

You can set the session lifetime to 10 minutes on the STS and 10 minutes on the RP and use the sliding session approach on the RP. After 10 minutes of inactivity both sessions would expire and the user should be required to re-authenticate.

If you have multiple RPs you could implement a form of keep-alive from the RP to the STS - e.g. load a resource from the STS in every webpage on the RPs. Whenever a page is loaded on an RP, the keep-alive resource would be loaded from the STS - refreshing the STS session. After 10 minutes of inactivity they would both time out and the user would have to re-authenticate.

"A resource from the STS" could mean a web page (Web Forms/MVC) loaded in an invisible iframe. The important thing is that it's a managed handler so the request is handled by ASP.NET.

As for your questions, if you sync the session lifetimes so they time out together:

  1. No, you don't need to add any code in the else clause. If the token is expired, WIF will redirect to the STS.
  2. Just remove the else clause.
  3. Let WIF handle this for you.

For completeness, if you can't sync the session lifetimes you could trigger a federated sign-out when the RP session expires. The following snippet triggers a signout at the configured Issuer (STS). You could put this in the else clause to trigger a signout on the first request after the RP session expires:

using System.IdentityModel.Services; //WIF 4.5

var stsAddress = new Uri(FederatedAuthentication.FederationConfiguration.WsFederationConfiguration.Issuer);
WSFederationAuthenticationModule.FederatedSignOut(stsAddress, null); //Optional replyUrl set to null

Hope that helps!

like image 155
klings Avatar answered Nov 17 '22 22:11

klings