Delete a session without the client

Does anybody know if there is a way to delete a session from the server without any interaction from the client.

A scenario being, a user is logged into their dashboard but they have just had their account terminated. What I’d like to do is delete the session so that the next time they click on a link, on any device they are logged in with, it’ll immediately see that the session no longer exists and kick them out.

When they log in I could record their CFID, CFTOKEN and SESSIONID. If they are logged in with multiple devices I’d have to store multiple sets then delete all of them.

Is this possible? I tried it on ColdFusion and failed, it just kept recreating it, it would not go away, possible to do with cookies but I thought once it’s gone server side, it’s gone.

Appreciate any input.

HTH

– Denny

1 Like

And Mark, FWIW, if you still have your app running on acf, this should work just the same there. (Thanks, Denny.)

1 Like

Unless I’m mistaken, that’s not going to work on its own as it requires interaction from the client. I believe, the OP is aking for a way for an admin to invalidate a client’s session?

While some client interaction would always be needed, the only reasonable way we’ve found to do this is to set a flag in each client’s session that gets checked on each request. The admin can flip that bit and then the next time the user makes a request, then sessionInvalidate() can be forced to run (also, note that sessionInvalidate() does not work with J2EE sessions)

Alternatively, there used to be a project that tried to manage individual sessions remotely, but it used a lot of undocumented Java calls in ACF and Lucee (then Railo…) I got it working, but found it to be unstable.

1 Like

Doh! You’re right. When I added my comment, I was thinking that function had a means to be passed the sessionid to be invalidated, but I see now that’s not listed as supported in either the lucee or acf docs.

But there are of course various underlying Java object calls that can do things not exposed in cfml. And as some know, cf has long had its undocumented sessiontracker object. That’s got a means to point to a specific session, and a setmaxinactiveinterval method that what I must have had in method that could set the timeout to a low value in seconds. It’s discussed, with code, here:

I’m writing from a phone so have not tested it on Lucee. Also that code loops over ALL sessions in an app, but it should be possible to see what’s used for the session identifier so as to terminate instead just some specific session. That’s what I was recalling was possible.

Let us know if it works out or not (whoever may try it).

1 Like

Agreed. From the sound of the OP’s post he had everything figured out except how to invalidate the session… but you’re right, and I should have elaborated on the full solution beyond just posting the function… if nothing else so others would have a full picture of a working aolution.

Thanks for elaborating a full solution. :slight_smile:

— Denny

whoops, I missed the updates to this thread. @carehart well, I am currently developing on CF2016 still, but I’ve got the new platform on Lucee. I have yet to take a minute to get both CF and Lucee running on my dev side so I can then dev in the same as prod, which I’m thinking is a pretty good idea :slight_smile: I should add the reason for this is a site I have does not run on Lucee as it creates too many cookies, I tried to resolve this and failed back in August 2023, so once I figure that out I can leave CF, but until then I need both

Yes, I’ve got everything figure out (I think) aside from deleting the session. Now I do have a flag in the session that is checked by the application to ensure they are logged in. If there was a way for me to delete or change the value of that session value if I knew the CFID/TOKEN which I can record at log in, then when I suspend the user, I could make that change and their next interaction would indeed invalidate them. I am a little concerned about them being logged in on multiple devices and how I would make sure that I am only storing a list of active sessions so I can flag them all… umm this could be a can of worms.

Alternatively, every time they hit a page I’ll have the session increase a counter, every X number of hits I will query the database for their status, rather ugly, and not perfect but I could get them out on every 10 or so interactions. I don’t think my SQL database would vote for it.

As I mentioned above, just set a flag - e.g. a timestamp or boolean in the application and session scopes - then have your clients check their timestamp vs. the one in the application scope and if different, fire sessionInvalidate() On your end, just change the timestamp for the client in question to a different value and on their next request they’ll be logged out.

Alternatively, you can play with the undocumented sessiontracker object. I’ve had success getting that to work, but experienced some stability issues and so abandoned the practice.

I got a little side tracked wrapping up my project and need to circle back to this.

I’m not quite sure what the solution is, if any.

@Leftbower are you saying that I can change a value related to their session from my server side in my dashboard without any client interaction? If I can manipulate values in the session without the client then I could remove the flag that indicates they are signed in, so next time they click on a page, they would be kicked out.

I still have the issue of thinking about how I handle it when they are logged in on multiple devices with different sessions. I’d have to log them all in their account, and when I suspend their account make changes on all sessions (if that’s possible). Housekeeping it might be a pain.

Appreciate any further clarification. Thanks.

Correct.

I don’t see a problem. Whatever unique identifier that you use for the “user” in the scenario above will be the same for every instance they are logged in? For instance, maybe you keep an array in the application scope with the userName. Then have a method in onRequestStart() that checks if that user exists, and if not, run the sessionInvalidate(). On the admin side of things, remove the particular user’s userName from the application scoped variable when you want to force all instances of their login to be invalidated on their next request.

I’m not quite sure how that works.

When the user logs in I set a value in the session. So let’s say that’s session.aff_uid

The value is checked in the application.cfm and it does not exist, they are kicked out to the log in page.

They can log in on multiple devices, and that would give them a sessionid cftoken and cfid

So the plan would be to record these values into their record, so I could go to my internal dashboard and disable an account and at the same time delete the session as I’d know the sessionid/cftoken/cfid (just a theory as I’ve never done this)

So if they are logged in with multiple devices I would need to know which sessionid’s that have created for all time, as they could have expired but not been updated in the database

I suspect due to my lack of knowledge on session management that I might be misunderstanding and going the wrong way about it and I’m just not understanding your approach.

I think you are overthinking a bit. For example, let’s say you have an app with a login system. Then each user should have a unique ID per user (as opposed to per session) - let’s call it uniqueUserID .

So, quick and dirty, you could have an array in the application scope called needsToLogout and every time you want to force a user to logout wherever and whatever device they’re logged in on, you go to your Admin dashboard and add their unique user ID to the needsToLogout array.

In your application, for every request (i.e. in onRequestStart() or whatever your app/framework might provide) you do a simple and quick check… something like:

if( application.needsToLogout.contains( uniqueUserID ) ){
    // run session user cleanup code here, like...
    sessionIvalidate();
}

The next request that user makes - on any and all systems he’s logged in on - his session will be invalidated and he’ll be forced to re-login. If his credentials have been revoked, he’ll be unable to do so.

So that array contains a list of all ID’s that need to be logged out, and I write the same array to all scopes

So that all sessions get to be compared to that list?

Ah, strike my comments above I get it now. My skill set is a little limited, i never progressed to guru or close :slight_smile:

I’ve never used the application scope, now I get it

So I add the user to the users UID to an application value which is shared across the entire application

Then on every call in the application.cfm I check if their user UID is in that list and if so, log them out and delete the session.

So if I maintain that application.LogoutList in the application.cfm file, will I need to recreate the application.cfm file to add them to that list? Or is there a more elegant way of handling that?

Another thought, I’d never know how many devices the user was logged in on and if they were indeed logged out of them. Short of knowing when the session would time out, so it would either when they click on a link and they are kicked out, or the session times out. So with regards to maintaining that list I would have to keep their ID in it until I know the session has passed its expiry time then I could do some housekeeping, but it’s quite a bit of work to record, track and action that. Only other option is keep them in the list, I don’t think the list will be that big anyway.

I’m going to ask a silly question, but is there any way for me to access all of the sessions that are currently stored and then search the values? That way I could search for the user UID and delete them all.

Well, as I said here:

I don’t want to take the risk of any problems.

I guess for simplification I could just maintain a list of ID’s let’s say BlockedUIDS that should not be allowed into their dashboards, either in the application.cfm which I’d have to use code to recreate if I added another, of a template that the application.cfm calls and in that template define a variable that has a list of ID’s

Then in either approach, have the application check if the logged in user is in the list, and if so, kick them out.

I was thinking about house keeping on the list, although I don’t think it will grow much. I should be able to delete the UID from the list after the time the session is set to last expires, because the user would have either been kicked out on all devices, or they would have clicked and been kicked out so the session could not be extended.

I would not involve the application scope in any of this. That’s for stuff relating to the application; not users of the application.

This is all around a user.

A user will be represented by a user object, likely backed by a row in a users DB table or something.

The user will have an active property, wherein the user needs to be active to be able to use the application. If they’re inactive, they cannot use the system (and should not be logged in, if they already are).

So when a user makes a request… check if they’re active. if they’re not: invalidate their session. Job done.

You don’t need to do any of this behind the scenes or “without the client”, because a user’s session (in the CFML sense of the term) only matters when the user with that session comes to use it. If they’re not using, it’ll timeout of its own accord after the timeout period. If they try to use the session when their user account is inactive: turf them out. But you only need to do that if they’re trying to use it.

I think you are overcomplicating things.

@AdamCameron You’re right, there’s a DB table which contains the userUID and also a UserStatus.

When they are logged into their dashboard the session has a flag which contains their userUID. If that does not exist the application.cfm will kick them out.

If I go to my internal dashboard and disable them, it will change their UserStatus in the database, let’s say to 0

Now, if they are logged into their dashboard on multiple devices, the session will indeed time out eventually, however, if they continue to revisit the dashboard, then the session won’t time out, and therefore they won’t be kicked, certainly not immediately.

Are you saying that on every hit of a page I query the database to check their status?

Yes. Because that’s when you need to know.

I’m not big on a database query for every page hit by every user as they navigate their dashboard.

Would it not be more efficient, to have a list and then have it just check if the userUID is in that list