Ask a Jedi - Why isn't my session expired when I logout?

This post is more than 2 years old.

Mark asks a question which I think touches on a basic misunderstanding many people have with ColdFusion and sessions:

I am developing an AJAX RSS feed reader for a portal. I've read several proposed methods of handling sessions, but I don't any address my specific need. In order for the client script to retrieve external feeds I have setup a proxy which simply checks whether it is given a valid URL, it grabs the feed and caches it for a minute so that common feeds don't spawn external GETs more than once a minute. Also, If users leave their portal page open, the client will update the feeds every few minutes.

What I don't want is the portal session timeout to be affected by the feeds being retrieved via the proxy, so I put it in its own subfolder with its own Application.cfm. For some measure of security, I want to require that the client has a cookie with a valid, unexpired session. In order to check this cross-application (proxy->portal) I'm using this in Application.cfm:

<cfset a = ArrayNew(1) />
<cfset sessionClass = a.getClass().forName('coldfusion.runtime.SessionScope') />
<cfset sess = StructNew() />
<cfset sess.expired = sessionClass.getMethod('expired', a) />
<cfset tracker = createObject("java","coldfusion.runtime.SessionTracker")>
<cfset sessions = tracker.getSessionCollection('PORTAL')>
<cfset expired = sess.expired.invoke(sessions['PORTAL_'&PORTAL_Session], a)>

Now I should be able to check whether expired is true/false, right? ..Nope. Expired only seems to change when the timeout has been reached, apparently it is not set to true when the user clicks logout.

So first off - it is critical you understand that - out of the box - there is no way for you end a user's session. Just because a user clicked "Logout", it does not end his session. I assume your logout code does something like this:

<cfset structDelete(session, "loggedin")>

While this removes data from the session, and may remove the only key you ever set, this did nothing to end the session. The user still has a session and will continue to have one until timed out by the server.

You may be able to find an API in ColdFusion to truly kill the session, but it isn't officially supported. I like to play around with the undocumented APIs too, but I always recommend against this. You have no guarantee it will work.

So obviously there are multiple other ways you can solve this. I think the cookie approach is best. In your main application, I'd simply set a cookie called "LASTHIT". On every request, set it to now.

In your sub application, see if LASTHIT was set more than 20 minutes ago. If so, consider the request invalid.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Joe Mastroianni posted on 5/1/2008 at 7:16 PM

What if you structDelete session.sessionID? I haven't done it but wouldn't that make the session irretrievable?

That's probably horrible practice though.

Comment 2 by Todd Rafferty posted on 5/1/2008 at 7:37 PM

In my session.user object, I have a function called isLoggedIn() which returns true/false. I also have a logout() function that flips the true to false and the Application.cfc or Application.cfm has a "bouncer" that is constantly checking isLoggedIn() - if it returns false, then bye bye - cflocated.

Comment 3 by Todd Rafferty posted on 5/1/2008 at 7:39 PM

Oh, the additional point I forgot to make. I don't kill the session, I just re-init the object via session.user's init() function.

Comment 4 by David posted on 5/1/2008 at 8:14 PM

Ray - correct me if I'm wrong, but CF Enterprise offers another dimension to ending sessions if you use J2EE sessions. It *should* kill the session when the browser is closed.

Cheers,

Davo

Comment 5 by Joe Mastroianni posted on 5/1/2008 at 8:18 PM

Not to rip on CF (it's my livelyhood and all) but what CF *should* do and what it *does* do are two very different things sometimes. From my understanding, when the browser is closed, the J2EE session is effectively 'orphaned' but doesn't actually get destroyed until the timeout is reached.

Comment 6 by Todd Rafferty posted on 5/1/2008 at 8:27 PM

@David/Davo: My understanding is that J2EE doesn't kill the session when the browser is closed. It just makes sure that you can't go back to the previous session upon returning to the site. The session will time out naturally.

Comment 7 by Todd Rafferty posted on 5/1/2008 at 8:28 PM

btw, I don't think J2EE sessions is limited to CF Enterprise.

Comment 8 by David posted on 5/1/2008 at 10:22 PM

That was my experience Todd, and at least now I know it wasn't something I forgot to set in the Admin. That would be a nice feature for CF 9 :-)

Davo

Comment 9 by Goyuix posted on 5/1/2008 at 11:36 PM

For what it is worth, and I apologize for being very slightly off-topic: I usually just nuke the CFID and CFTOKEN cookies - which doesn't expire the session as such, it orphans it much the same way that "closing the browser" does. If the user makes a request after "Logout", the application generates a new CFID and CFTOKEN, as well as a brand-spankin' new session scope.

Side note: It would be very nice if CF provided a way to recycle/expire a session through code. Free up some resources immediately rather than wait 20 minutes.

Comment 10 by Todd Rafferty posted on 5/2/2008 at 2:15 PM

@Goyuix, I used to the same until I took a drink from the J2EE session koolaid. You don't have to set the CFIDE/CFTOKEN cookies anymore when you use the J2EE sessions.

Comment 11 by dcs posted on 8/18/2009 at 9:13 PM

"What if you structDelete session.sessionID? I haven't done it but wouldn't that make the session irretrievable?"

If you do this CF won't create another session.sessionID until you close the browser and open a new one (or, I assume, until the session expires). It has no effect at all if you're using J2EE sessions.