Re: [Catalyst] Preventing simultaneous logins

2008-07-26 Thread Daniel McBrearty
Thanks Matt, I'll definitely try this when I get round to trying to
solve this issue.

Where does MyApp::set_athenticated get called from? when the user logs
in? no, that can't be it ... you're way ahead of me here :-) ...

  1. checking whether there is an existing session associated this username
 
  Session::PerUser ?
 

 I looked briefly at this, but I'm a bit wary because
 C::P::Session::Store::Fastmmap warns against being used with it. What
 is PerUser doing that is special in that respect, and what is a good
 backend for it?

 REading the docs for it, it seems like something slightly different -
 keeping the same session in place, even if the user logs in in the
 middle of it, if I understand correctly?

 You want:

 login from elsewhere to log out the same user anywhere else

 It wants:

 any login by the same user claims the user's session

 so, if you add in your root auto

 if ($c-user_exists) {
  unless ($c-user_session-{sid} eq $c-sessionid) {
$c-logout;
$c-forward('/auth/logged_out');
return 0;
  }
 }

 and in MyApp

 sub set_authenticated {
  my $self = shift;
  $self-next::method(@_);
  $self-user_session-{sid} = $self-sessionid;
 }

 then you should pretty much be done.

 So far as I can tell, this is perfect for you. You just sometimes get
 persistent session data as well (it warns against fastmmap because in the
 persistent session use case fastmmap is lossy - in yours the lossyness
 is irrelevant, you don't care about the persistence feature)

 --
  Matt S Trout   Need help with your Catalyst or DBIx::Class project?
   Technical Directorhttp://www.shadowcat.co.uk/catalyst/
  Shadowcat Systems Ltd.  Want a managed development or deployment platform?
 http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/

 ___
 List: Catalyst@lists.scsys.co.uk
 Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
 Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
 Dev site: http://dev.catalyst.perl.org/




-- 
There's an infinite supply of time, we just don't have it all yet.

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Preventing simultaneous logins

2008-07-26 Thread J. Shirley
On Sat, Jul 26, 2008 at 12:56 PM, Daniel McBrearty
[EMAIL PROTECTED] wrote:
 Thanks Matt, I'll definitely try this when I get round to trying to
 solve this issue.

 Where does MyApp::set_athenticated get called from? when the user logs
 in? no, that can't be it ... you're way ahead of me here :-) ...


The base is from Catalyst::Plugin::Authentication:

http://search.cpan.org/~jayk/Catalyst-Plugin-Authentication-0.10006/lib/Catalyst/Plugin/Authentication.pm#set_authenticated(_$user,_$realmname_)


But C::P::Session::PerUser has its own which handles merging the session.

-J

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Preventing simultaneous logins

2008-07-25 Thread Daniel McBrearty

 1. checking whether there is an existing session associated this username

 Session::PerUser ?


I looked briefly at this, but I'm a bit wary because
C::P::Session::Store::Fastmmap warns against being used with it. What
is PerUser doing that is special in that respect, and what is a good
backend for it?

REading the docs for it, it seems like something slightly different -
keeping the same session in place, even if the user logs in in the
middle of it, if I understand correctly?

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Preventing simultaneous logins

2008-07-25 Thread Moritz Onken


Am 25.07.2008 um 10:27 schrieb Daniel McBrearty:



1. checking whether there is an existing session associated this  
username


Session::PerUser ?



I looked briefly at this, but I'm a bit wary because
C::P::Session::Store::Fastmmap warns against being used with it. What
is PerUser doing that is special in that respect, and what is a good
backend for it?

REading the docs for it, it seems like something slightly different -
keeping the same session in place, even if the user logs in in the
middle of it, if I understand correctly?



You shouldn't store a session in a store which might lose the session
because it runs out of memory. Use a store which stores the session
permanently like DBIC.


cheers


___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Preventing simultaneous logins

2008-07-25 Thread Matt S Trout
On Fri, Jul 25, 2008 at 10:27:34AM +0200, Daniel McBrearty wrote:
 
  1. checking whether there is an existing session associated this username
 
  Session::PerUser ?
 
 
 I looked briefly at this, but I'm a bit wary because
 C::P::Session::Store::Fastmmap warns against being used with it. What
 is PerUser doing that is special in that respect, and what is a good
 backend for it?
 
 REading the docs for it, it seems like something slightly different -
 keeping the same session in place, even if the user logs in in the
 middle of it, if I understand correctly?

You want:

login from elsewhere to log out the same user anywhere else

It wants:

any login by the same user claims the user's session

so, if you add in your root auto

if ($c-user_exists) {
  unless ($c-user_session-{sid} eq $c-sessionid) {
$c-logout;
$c-forward('/auth/logged_out');
return 0;
  }
}

and in MyApp

sub set_authenticated {
  my $self = shift;
  $self-next::method(@_);
  $self-user_session-{sid} = $self-sessionid;
}

then you should pretty much be done.

So far as I can tell, this is perfect for you. You just sometimes get
persistent session data as well (it warns against fastmmap because in the
persistent session use case fastmmap is lossy - in yours the lossyness
is irrelevant, you don't care about the persistence feature)

-- 
  Matt S Trout   Need help with your Catalyst or DBIx::Class project?
   Technical Directorhttp://www.shadowcat.co.uk/catalyst/
 Shadowcat Systems Ltd.  Want a managed development or deployment platform?
http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Preventing simultaneous logins

2008-07-24 Thread Octavian Rasnita
From: J. Shirley [EMAIL PROTECTED]
 It's fairly simple to track user login now.  You can have an automatic
 ping from the browser to the server that updates the session time.
 Just put it in your template wrappers so you have some simple request
 (even something like an action that renders an image, and a javascript
 timer that reloads that image every X number of seconds).

The javascript code could be avoided, so it is not a problem if the browser is 
not set to support javascript.
If the current user doesn't access a new page in 10 (or 15, 20...) minutes, 
then his session expires and he could log in again on another computer.

If a company has a username for accessing a newspaper, and if an employee of 
that company accesses the site, he should be able to read the newspaper even if 
another employee tries to log in.

But if the first user doesn't access a new page every 10 minutes, his session 
should expire and allow the other users to log in, even if he stays logged and 
doesn't close his browser.

 That way you can set your lockout time to a ridiculously low level so
 the user doesn't have to wait for the session to clear.

If the lockout period is too low, the session might be closed much earlier than 
it should so it should be set depending on the situation, because the browser 
might not use Javascript, and the user might not access a new page often enough.

 I think the points about the problem are perfectly valid though, it's
 a hard problem to solve right, because right is very use case
 specific and the protocol itself is the problem.

Yes of course. But in any case, I think that a new login should not disable a 
previous login, because any new user will log off a previously logged user. In 
that case the logged off user will try to log in again and he will logg of the 
other user and so on, and this will not be very nice...

A logged user must stay logged while he actively uses the page.
If he doesn't *actively* use the page, his session must be disabled, even if he 
leaves the browser opened. That's why I think that no javascript should be used 
to ping the server, but consider it *active* only if he accesses new pages at 
least from 10 to 10 minutes, or another period, depending on the specific 
situation.

Octavian


___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Preventing simultaneous logins

2008-07-23 Thread Jonathan Rockway
* On Wed, Jul 23 2008, Daniel McBrearty wrote:
 What I'd like to do is check if this user is already logged in at some
 other computer, and deny access if so.

I would probably store sessions in the database, and then store the
session ID in the user table at login time (current_session) or
something.  Then when they log in again, you can join in the session
row, check the expiration time in that row, and then allow/deny the
login.  You can also use that opportunity to delete the session from the
database so that the other machine no longer has a valid session.

I don't think the file-based session stores provide this much
flexibility, but you could probably hack something similar if you really
needed to.

Regards,
Jonathan Rockway

-- 
print just = another = perl = hacker = if $,=$

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Preventing simultaneous logins

2008-07-23 Thread J. Shirley
On Wed, Jul 23, 2008 at 1:12 PM, Jonathan Rockway [EMAIL PROTECTED] wrote:
 * On Wed, Jul 23 2008, Daniel McBrearty wrote:
 What I'd like to do is check if this user is already logged in at some
 other computer, and deny access if so.

 I would probably store sessions in the database, and then store the
 session ID in the user table at login time (current_session) or
 something.  Then when they log in again, you can join in the session
 row, check the expiration time in that row, and then allow/deny the
 login.  You can also use that opportunity to delete the session from the
 database so that the other machine no longer has a valid session.

 I don't think the file-based session stores provide this much
 flexibility, but you could probably hack something similar if you really
 needed to.

 Regards,
 Jonathan Rockway

 --
 print just = another = perl = hacker = if $,=$


I agree this is the way to go, and it would be pretty easy to write a
Credential that inherits from Password that does the additional check
before succeeding.

That way your controllers stay thin, and this feature is more easily
tuned and configured.

-J

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Preventing simultaneous logins

2008-07-23 Thread Wade . Stuart
Daniel McBrearty [EMAIL PROTECTED] wrote on 07/23/2008 02:47:57
PM:

 I'm using Cat with a pretty standard configuration of :

 Catalyst::Plugin::Authentication
 Catalyst::Plugin::Session
 Catalyst::Plugin::Session::State::Cookie
 Catalyst::Plugin::Session::Store::FastMmap

 to handle login and session management. My login code looks like this:

  my $u = $params-{username};

   if ($c-authenticate( { username = $u,
   password = $params-{'password'}
 } )){
 my $user = $c-user;
 $user-last_login(DateTime-now);
 $user-update();
 $c-response-redirect( $forward, 301);

   } else {
 # login failed
 $c-stash-{login_failed} = 1;
   }


 What I'd like to do is check if this user is already logged in at some
 other computer, and deny access if so. I guess that means :

 1. checking whether there is an existing session associated this username
 2. Being sure that the associated session is cleared when the user
 hits 'logout'

 I did a quick search and didn't get anything on the list - any quick
 clues about the easy way to do this, before I start digging into the
 guts of the plugins to see how?

 many thanks

Daniel,

  This is actually a pretty hard problem -- there is no right answer.
What if the user clears her browser state while using the site?  Leaves the
computer and browser on at work then tries to log in at home on a different
computer?  I think you can gain most of the lockdown of 1 session per user
if you just track user activity over a X minute period.  for instance every
time a user hits your app add a record that is attached to the user account
in the db (src ip, session number, other relevant info).  Then do (either
inline or if it is too costly,  via cron) a check on those entries that
looks for multiple IP/Sessions or whatever you define as multiple users
(given that http is stateless there really is no _safe_ definition).  If
that process detects usage over your threshold,  disable (temp or
permanent) the account.  The same process can clean up entries that are
outside of the time window that you want to look at.




___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Preventing simultaneous logins

2008-07-23 Thread Tomas Doran


On 23 Jul 2008, at 21:20, [EMAIL PROTECTED] wrote:


  This is actually a pretty hard problem -- there is no right  
answer.
What if the user clears her browser state while using the site?   
Leaves the
computer and browser on at work then tries to log in at home on a  
different

computer?


I agree that it's a hard problem if you do it the original way round  
that was suggested.


However all apps which do that (Facebook as an example) - logging  
into a new session kills your old one, and this is pretty easy to do  
(given that you force users to have a cookie and etc).



I think you can gain most of the lockdown of 1 session per user
if you just track user activity over a X minute period.  for  
instance every
time a user hits your app add a record that is attached to the user  
account
in the db (src ip, session number, other relevant info).  Then do  
(either
inline or if it is too costly,  via cron) a check on those entries  
that
looks for multiple IP/Sessions or whatever you define as multiple  
users
(given that http is stateless there really is no _safe_  
definition).  If

that process detects usage over your threshold,  disable (temp or
permanent) the account.  The same process can clean up entries that  
are

outside of the time window that you want to look at.


If you in any way expect your site to scale to high volume, I'd  
highly recommend avoiding any approach like this.


Your 'hit logging' table is going to be really really slow (and have  
massive contention) if you're doing high volume. Also - these lookups  
for multiple IPs you're talking about, they're not going to be  
indexed, right? (Adding a *single* index on a table will reduce your  
max insert speed by 40-60%).


Even if you're cleaning out rows pretty regularly, you're going to  
seriously grind the IO on the DB system, and the general IO subsystem  
on your database server (not to mention any replication / binlogs /  
hot backups  etc that you need), is going to be doing significantly  
more work than it needs to, meaning that the general amount of  
headroom you have in the system will be that much reduced...


Your session storage could be criticized for the same reasons, but is  
actually significantly less work for the DB (updating, not inserting  
and deleting - 1/2 the IO and no index overhead as you're re-writing  
without changing keys), and can _trivially_ be pushed into memcache  
at a later date when you need to. The approach recommended above  
requires a relational model, and so moving it to memcache wouldn't  
work...


All of that said, unless you're looking to scale to multiple Mb/s of  
traffic, then I'm probably being too paranoid - as jay said already,  
'right' here is use-case specific :)


Cheers
t0m


___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Preventing simultaneous logins

2008-07-23 Thread Daniel McBrearty
indeed, it is use case dependent.

The use case here is a common one, free content, paid content, you
don't want users giving their creds to all their friends and using it
simultaneously.

(It is at best a first order solution, obviously if it becomes obvious
that a fair percentage are using the system 24/7, something better is
needed (say, bw capping). Not to hard to do, if needed.)

As for the other points :

1. hadn't considered people closing the browser, without logging out -
thanks. I guess a short session time is needed - say 10 minutes. The
idea of pinging using javascript is quite neat, but I dislike the idea
of making the server handle say 2 unproductive req's per minute per
logged in user. I'd even rather something as ugly a js popup saying
If you close without logging out ... when the user closes while
logged in to that, I think.

2. the issue of someone leaving work with their browser left logged in
is pretty insoluble (after all the browser could well be left open, so
you still rely on session timeout). If they do it, they have to wait
the 10 minutes, or go back to that computer and log out. K-I-S-S ...

If you do all that, so that logout will always happen, couldn't you
then solve it like this? (There may be a big fat hole in this ... this
is hardly my specialist area ...):

1. On successful login (ie good U/P), get last session key for that
user which you left in the db last time.
2. Look in the store for that key, see if it has timed out
3. If so, actually log in and write the new key to the db.
4. Otherwise, fail and leave the db alone.
5. On a real actual logout, nullify the key in the db and take it out
the session store.

That has only one db write per login (and I store last_login time
anyhow, so no real increase), and the session store stays out of the
db.

Regarding volume, well, it's hardly an issue today, but you never know ...

thanks for the excellent quality of feedback

Daniel

-- 
There's an infinite supply of time, we just don't have it all yet.

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Preventing simultaneous logins

2008-07-23 Thread Matt S Trout
On Wed, Jul 23, 2008 at 09:47:57PM +0200, Daniel McBrearty wrote:
 I'm using Cat with a pretty standard configuration of :
 
 Catalyst::Plugin::Authentication
 Catalyst::Plugin::Session
 Catalyst::Plugin::Session::State::Cookie
 Catalyst::Plugin::Session::Store::FastMmap
 
 to handle login and session management. My login code looks like this:
 
  my $u = $params-{username};
 
   if ($c-authenticate( { username = $u,
   password = $params-{'password'}
 } )){
 my $user = $c-user;
 $user-last_login(DateTime-now);
 $user-update();
 $c-response-redirect( $forward, 301);
 
   } else {
 # login failed
 $c-stash-{login_failed} = 1;
   }
 
 
 What I'd like to do is check if this user is already logged in at some
 other computer, and deny access if so. I guess that means :
 
 1. checking whether there is an existing session associated this username

Session::PerUser ?

 2. Being sure that the associated session is cleared when the user hits 
 'logout'

after logout = { shift-delete_session };

-- 
  Matt S Trout   Need help with your Catalyst or DBIx::Class project?
   Technical Directorhttp://www.shadowcat.co.uk/catalyst/
 Shadowcat Systems Ltd.  Want a managed development or deployment platform?
http://chainsawblues.vox.com/http://www.shadowcat.co.uk/servers/

___
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/