Help with concurrent login

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

User avatar
peetz
Forum Newbie
Posts: 14
Joined: Mon Oct 10, 2005 1:49 pm

Help with concurrent login

Post by peetz »

Got a problem with a user authentication system i'm trying to implement.

Basically, i'm trying to extend my current system to stop/limit concurrent user login (i.e. a user can only be logged in once at any one time).

Thought of ways to do this:

1. Store session_id in the database when user logs in and check each time page is loaded for authentication. Stop users logging in with correct username/password but different session_id.

2. Store an variable in the database which is updated when users login. Stop users logging in with correct username/password if this variable is set.

3. Store a list of users which are currently logged in. Stop users logging in with correct username/password if username already in this list.


All three will work in theory BUT there is a problem. If a user logs out then this will work fine because we can deal with clearing or removing data from the database when this happens. The problem occurs when a user simply closes their browser or their session times-out. As far as i'm aware, there is no way to solve this without re-writting the php session handler. Bugger that!

Any ideas? I'm really stumped! I've searched forum after forum ... no luck.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

although I know this topic has come up previously, I can't find the original I'm thinking of.. so I'll go over the basics:

Using a database table, you record the session's (and thus the user's) last communication with the server. If their record is not in the table, let them log in. If their last communication with the server was some time ago, let them login. It's basically like a who's online script, in fact it's the underlying system to create one basically..

There are multiple threads that talk about who's online or similar namings...
User avatar
peetz
Forum Newbie
Posts: 14
Joined: Mon Oct 10, 2005 1:49 pm

Post by peetz »

Thanks for pointing me in the right direction. I knew it was something fairly simple.

Decided to store last_logged_in timestamp along with the session_id in the database and set a time-out to something like 5 minutes (for arguments sake).

However, if a user is idle for longer than 5 minutes ( e.g. reading a certain page), when they then decided to click to view a different page they would be required to log-in again. If I set the time-out to something more realistic for viewing a page (i.e. 20 minutes). This means a user who was interrupted (e.g. browser crashed, clicked close window accidentally) would need to wait for the remainder of the 20 minutes to log back in.

Any suggestions on how to overcome these conflicting problems?
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

Simply don't. Most systems don't have any problem with multiple authentication requests coming from different(?) locations. Emphasis on different. There is no reliable way to determine whether or not a client is the same one as you talked to last time. So then it boils down to:

Disallowed time after last communication to log in.

As you can see, there is one end where the allowed timeframe is small, there is a security risk(?), when the timeframe is big, there's a usability risk.

Do yourself a favor and don't implement it at all. Unnecessary feature creep for a dubious security risk (if they know the credentials, they'll just log in later).

However, if you insist, here's the solution: make the disallowed window for the login different from the session expiration. A session can last, say, one hour, but the login is disallowed for the immediate five minutes after the log in.
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

You could use xmlhttp to make calls to the database every 5 seconds.. or even use an iframe that reloads every x seconds updated their "last active" time
User avatar
peetz
Forum Newbie
Posts: 14
Joined: Mon Oct 10, 2005 1:49 pm

Post by peetz »

Thanks for the replies.

Jcart: I've looked into the XMLHTTP requests but it seems a bit complex for what I need (unless you have a simple example I could look at). Seems I could request a server-side script every x seconds/minutes which updates the database.

Ambush Commander: Not sure what you meant by "Unnecessary feature creep for a dubious security risk" but I do need to do this. The reason I need this to work is to stop concurrent logins from users so that I can track misuse (i.e. I can almost certainly say that the person logged in is the person who owns the account). I also need to stop users registering once and giving friends, etc. their account details. I think preventing concurrent logins would stop this.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Create an identity profile of their Client Browser, IP, and some other unique (well, fairly variable) details. If it changes while they are essentially logged in - force a logout, and request the login details again. That's one way to discourage concurrent use. Also make sure sessions are not being passed by URL - only by cookies (will only stop the utter incompetents but every little helps) in conjuntion to your session id tracking.

I say this because users can copy session ids - it's a known security risk. In your case, they could intentionally share the id whether from the url or a cookie.

Best bet is in the first line - keep logging them off if their client identity map changes - they'll soon get the message unless they are very persistent. If they are really persistent consider banning their accounts. To back that up add a paragraph to your site's terms of use which states account sharing, and concurrent logins are not allowed on your site. An ID map is temporary - but it could work in many cases.

I'll disclaim by adding IPs can be shared (e.g. a school network, LAN connection), browser versions are fairly limited, but it might at least identify some of the obvious misusers over time. Unfortunately here is no one pefect way of determining a truly unique ID for any client - do your best and you'll catch some of them however...

This is actually one of the one most common issues in PHP games...so I'll have to deal with it at some stage also ;). Maybe catch Roja on the forums - he probably has more concrete ideas.
User avatar
peetz
Forum Newbie
Posts: 14
Joined: Mon Oct 10, 2005 1:49 pm

Post by peetz »

Thanks.

Like this idea too. Means I don't have to keep refreshing within a time limit, etc.

So, i'm guessing if I regenerate a new session id on each log-in and store this, along with the users IP this should give a fairly unique combination. However, like you said, if the user is behind a proxy, etc. then they will share an IP. This means that users sharing IPs will only need to intentionally share their session id and their in.

My initial thought was to generate a GUID and store this in the database and cookie and match them. Again, if someone is going to the trouble of sharing a session id, they'll think nothing of sharing cookies too.

Any suggestions about other data I could store which would be unique to the user?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

IPs are entirely unreliable as a "unique" information source.. not only because several different users could be behind a single IP, but also because a user's IP can shift wildly within a request (AOL does this all the time)
User avatar
peetz
Forum Newbie
Posts: 14
Joined: Mon Oct 10, 2005 1:49 pm

Post by peetz »

Any suggestions what I could use in place of IP?
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

The stuff that won't likely change during a request - browser version, operating system version, etc.

Think of it like creating a small profile of the current user. If you include browser version (say IE's id string), and suddenly a user with the same session_id starts using Firefox - you know something has changed. In a case like that its time to force a logout. I remember creating a planning outline a while back but can't locate it (the problem with using multiple PC's ;)). But is a reference to something similar in the case of a session id being compromised by Chris Shiflett - http://shiflett.org/articles/the-truth-about-sessions

That's an interesting read for more than one reason...

My apologies for mentioning IPs - as feyd has stated they are notoriously unreliable. There's little more irritating than being kicked out of your login session because its been tied to your IP address (happens on some sites since I use a small dial up ISP).

I think Chris's article (esp. the later fingerprinting part) is more demonstrable than my rambling...:)
User avatar
peetz
Forum Newbie
Posts: 14
Joined: Mon Oct 10, 2005 1:49 pm

Post by peetz »

Thanks, great article.

Looks like the fingerprint idea is exactly what I need to use, coupled with the session id. I'll give it a shot.

Thanks all!! I'm sure i'll be back for some more advice ...
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

Here is another approach:

- Every time a user logs in, allow him to log in (this way, he'll never be locked out due to previous opened session and store an id (could be session id)
- Every time he requests a page test if the id is the one that it is valid.
-> user has logged in again -> id is invalid, thus user is logged out
-> user hasn't logged in again -> id is valid -> user has access
User avatar
peetz
Forum Newbie
Posts: 14
Joined: Mon Oct 10, 2005 1:49 pm

Post by peetz »

Not sure I understand what you mean.

The thing I am trying to prevent is having a user log-in more than once at a time.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

I'm not sure I followed all that (does it make sense??? ;))

I think the problem can be less of someone else logging in though the login system - and more whether two users have willingly shared a session_id (possible - I've even seen monkeys do it). The idea above was on a per request basis, rather than a per login basis...if you follow. In concurrent usage, only 1 login may be required...
Post Reply