0

I'm building a sort of a web app in PHP. I have a login form in a way that I store a token in a session variable that's basically telling the server the user is online (this is also then stored in the db). This token clears when the login form is displayed (new login... or on logout - not shown in the code here). I also store the session_id() in the database at successful login.

To prevent 2 sessions to be open (in same browser or different browsers), I do 2 type of checks:

  1. Would the user only open the 2nd tab after login, I check against this token and the http referrer. If the token is not empty (meaning someone is logged in) and the http referrer IS empty (meaning a new tab / window has been opened) I echo an error message ("you already have an open session...").

  2. Would the user have 2 tabs open before login, I check against this token and the session_id() in the DB and the current one. If the token is there (meaning someone is logged in) and the DB and current session_id() is the same (meaning we're still in the same browser), I echo an error message ("you already have an open session..."). Would the session_id() be different here, that would mean we're in another browser and I'm also checking against this.

I'm trying to, at the same time, prevent users from reposting the login form, meaning, I want them to avoid clicking on reload right after they login.

The problem:
With the above setup, if I click reload, the server will think it's the 2nd browser tab login (case #2 above) because the token will be the there and the session_id() will be the same too, and so it will echo the error message ("you already have an open session...").

Is there a way to combine the too and make sure that on login form reload nothing happens?

the code looks something like this (I tried to strip this off of unnecessary code, sorry if it's not 100% correct):

<?php function LoginForm() { 
$_SESSION['token'] = ''; ?>
<form action="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING']); ?>" method="post">
    Please enter your login details</div><br />
    Login ID<br />
    <input type="text" name="userid" /><br /><br />            
    Password<br />
    <input type="password" name="password" /><br /><br />
    <input type="submit" name="login" value="Login" />
</form>
<?php }

if (!empty($token_in_DB) AND !isset($_SERVER['HTTP_REFERER'])) {
    echo "You are already logged in on another tab / window";
    exit();
} elseif (isset($_POST['login'])) {
if (!empty($token_in_DB)) {
    if ($session_in_DB == session_id()) {
            echo "You are already logged in on another tab / window";
            exit();
    } else { 
            echo "You are already logged in on another browser / computer";
            exit();
            }
    } elseif (/* password is ok */) {       
        // login
        // set token session variable
        // add token to db   
    }
} elseif (empty($_SESSION['token'])) {
    LoginForm();
} ?>
benomatis
  • 5,536
  • 7
  • 36
  • 59

1 Answers1

2

I'm trying to, at the same time, prevent users from reposting the login form, meaning, I want them to avoid clicking on reload right after they login.

To prevent this, you should follow the POST-Redirect-GET pattern and ALWAYS redirect after a successful POST. i.e. If the login is successful, redirect them to a splash page or a home page etc.

Secondly, if the user is logged in and browsing via another tab, he or she will have the same session ID as the first tab. This is unless they've opened a new private browsing / incognito window or they're utilizing a proxy.

Wayne Whitty
  • 19,513
  • 7
  • 44
  • 66
  • I now have the login form on top of every page with an `exit();` at the end that would only be skipped in case of a successful login. Do you mean I should create the login page as a standalone page in order for this to work properly? – benomatis Jul 05 '13 at 11:14
  • you might have not received my previous note...? – benomatis Jul 09 '13 at 18:02
  • I have implemented this method and it works perfectly, thank you! – benomatis Jul 25 '13 at 13:52
  • to help those further who are looking for a practical implementation of PRG: look for timdev's answer in this post: http://stackoverflow.com/questions/7681755/i-am-confused-about-php-post-redirect-get. – benomatis Jul 25 '13 at 13:54