views:

1005

answers:

4

We have an application that does single sign-on using a centralized authentication server (CAS). We'd like to do single sign-out, such that if the user logs out of one application (say a front-end portal), the user is automatically signed out of all applications using the same single sign-on ticket.

The expectation would be that each application would register a sign-out hook (URL) with the CAS at the time of logon to that application. When the CAS receives the sign out request from one of the applications, it invokes the sign-out hook for all the application sharing the SSO ticket.

My question is this: is there a way to abandon an InProc session from a different session? I presume, since the HTTP request will be coming from the CAS server, that it will get its own session, but it is the session of the user that I want to terminate. I have pretty good idea of how to do this using a separate session state server, but I'd like to know if it is possible using InProc session state.

+1  A: 

No can do.

http://forums.asp.net/p/416094/416094.aspx#416094

x0n
+1  A: 

With InProc SessionState, you won't be able to access the data... With StateServer, you still will have a sticky scenario trying to access the correct API to remove the session.

You will most likely want to use a database backed state solution like the pre-packaged SqlServer state provider or a third party solution like DOTSS: http://codeplex.com/dotss

With the database backed solution, you will be able to lookup the state record in a table by session id and mark it as completed. These techniques will vary based on the provider you choose.

Jeff Fritz
+2  A: 

After doing a bit of digging around and considering the answers provided so far I've come up with an alternative that lets me continue to use InProc session. Basically, it consists of extending the HttpModule that already handles single sign-on to detected CAS sign outs and redirect the browser to the application sign out page.

Outline:

Sign-On:

  1. For each new single sign-on request, create a new SSO cookie and encode a unique value in it to identify the session (not the session id, so it isn't leaked).
  2. Construct the the sign-out callback url, encoded with the identifier, and register it with the CAS server.

Sign-Out:

  1. When a sign-out request is received from the CAS server, decode the identifier and store it in an application-wide cache. This needs to be pinned in the cache at least long enough for the session to expire naturally.
  2. For each request, look for the SSO cookie and check its value against the cached, signed-out session identifiers. If there is a hit, remove the SSO cookie and redirect the browser to the application's sign-out url.
  3. For each sign-out, check to see if there is an SSO cookie, if so, forward the sign-out request to the CAS. In any event, abandon the user's session, and sign them out of the application.

Page_Load:

  1. Check for the presence of the SSO cookie. If there isn't one, redirect to the sign out page.
tvanfosson
+1  A: 

Haha, well... It looks like you can. I was wondering myself if there was any way to do this, turns out, there is.

When you use InProc, the InProcSessionStateStore (internal class) persist the session state in an internal (non public) cache. You can access this cache through reflection and remove the session state manually.

using System;
using System.Reflection;
using System.Web;

object obj = typeof(HttpRuntime).GetProperty("CacheInternal", 
    BindingFlags.NonPublic | BindingFlags.Static)
        .GetValue(null, null);

if (obj != null)
{
    MethodInfo remove = obj.GetType()
        .GetMethod("Remove", BindingFlags.NonPublic | BindingFlags.Instance, 
            Type.DefaultBinder, new Type[] { typeof(string) }, null);

    object proc = remove.Invoke(obj, new object[] { "j" + state.SessionID });
}

The end result is, that the next request will take on the same SessionID, but the HttpSessionState will be empty. You'll still get the Session_Start and Session_End events.

John Leidegren