0

I have a web app that I would like to restrict to a single browser tab or window. So the idea is a user logs in and if they open a link in a tab/window or open a new browser tab/window it kills their session. I know many are against this but that's how the app needs to be.

The controller checks if the user is logged in via:

if (!isset($_SESSION['user_logged_in'])) {
    Session::destroy();
        header('location: '.URL.'login');
}

I have tried setting $_SESSION['user_logged_in'] to false if its true but then obviously you don't go any further than one page.

Is there a way to destroy the session when a new browser tab or window is opened? I'm guessing probably jquery/javascript but not across that side of things.

nikmav
  • 375
  • 1
  • 3
  • 12
  • 1
    The difficulty will probably be differentiating between a new window opening and the page being refreshed. – Kevin B Jan 20 '15 at 05:41
  • Maybe using some cookies ? Storing the value of the tabs Take a look at this: http://stackoverflow.com/questions/4079280/javascript-communication-between-browser-tabs-windows – Russo Jan 20 '15 at 05:45
  • See here. http://stackoverflow.com/questions/11008177/stop-people-having-my-website-loaded-on-multiple-tabs – desbest Dec 01 '16 at 13:24

3 Answers3

2

It's very complex to achieve, unfortunately.
And almost impossible to do it true cross-browser and supported by every browser.

Technically, every new browser tab doesn't differ from the latter, form server's point of view. They share cookies and session too.

The only things that differ is JavaScript session. Say, an example: a site that is fully AJAX-based. First page is always login page. Then everything's changed with AJAX. If you dare to open another tab with this site it will open the first page which is always logging you out be default, for example. This can make it possible, but it's very complex.

New technologies stack like localStorage might make this possible, where you can communicate between tabs sending messages in localStorage. But this isn't fully cross-browser and isn't supported by all browsers versions.

So if you are ok with only limited choice of latest browsers — then dig on localStorage and postMessage.

Oleg Dubas
  • 2,320
  • 1
  • 10
  • 24
0

Just to piggy back on what Oleg said, it would be incredibly difficult since HTTP is stateless and browser tabs share data. One potential way of doing it COULD be on the front end, but a very specific set of circumstances would need to be present and they could easily be bypassed. IF the application is a SPA and the primary body is only loaded once, you could potentially generate a key on the body load and send that with each request. Then, if the body is reloaded (say in a new tab or new window), you could generate a new key which would start a new session.

However, the real question is why you would want to do this. Your user experience will suffer and no real security gains exist.

Kevin Eaton
  • 100
  • 3
  • 13
  • The main reason is to prevent a user from opening the same customer profile twice saving different data to each or processing a payment twice because they didn't refresh both tabs. Abit like my internet banking doesn't allow me to open multiple tabs which is fair enough because I might transfer money in one tab walk away look at tab 2 and do the same thing. multiple transaction to the same person are allowed but how does the system know it was intentional or not? – nikmav Jan 21 '15 at 02:50
0

I have some solution and I want share it with you.
To restrict user to only one tab per session, you may use cookie. I describe here how you may build your webapp in order to archieve that goal.

  1. Each time the web module needs to render the auth/login page, create and store a cookie with a given name. Let's call it browserName. The value of the cookie must be a generated value. You may use java.util.UUID if your programming language is java.
  2. When the browser finished loading your auth/login page, set the browser's name with the generated cookie value. You have to know how to read cookie using JavaScript.
  3. Each time the user load other page than auth/login page, check whether the current browser's name is that one stored in the cookie. If they are differents, prompt user and then you can run a snipt that reset session and redirect to auth/login page.

The following is an example of implementing what I've said.

  1. Snipt to be added in the method that runs before your login page in shown
    Map<String, Object> v$params = new TreeMap<>(); v$params.put("path", "/"); FacesContext.getCurrentInstance() .getExternalContext() .addResponseCookie("browserName", UUID.randomUUID().toString(), v$params);
  2. The mini JavaScript library that help you with cookie and other. Add it globally in your webapp.

/**
 * http://stackoverflow.com/questions/5639346/shortest-function-for-reading-a-cookie-in-javascript
 */
(function() {
 function readCookie(name, c, C, i) {
  if (cookies) {
   return cookies[name];
  }

  c = document.cookie.split('; ');
  cookies = {};

  for (i = c.length - 1; i >= 0; i--) {
   C = c[i].split('=');
   cookies[C[0]] = C[1];
  }

  return cookies[name];
 }
 
 window.readCookie = readCookie; // or expose it however you want
})();
// function read_cookie(k,r){return(r=RegExp('(^|;
// )'+encodeURIComponent(k)+'=([^;]*)').exec(document.cookie))?r[2]:null;}
function read_cookie(k) {
 return (document.cookie.match('(^|; )' + k + '=([^;]*)') || 0)[2];
}

/**
 * To be called in login page only
 */
function setupWebPage(){
 window.name = read_cookie("browserName");
}

/**
 * To be called in another pages
 */
function checkWebPageSettings(){
 var curWinName = window.name;
 var setWinName = read_cookie("browserName");
 
 if( curWinName != setWinName){
  /**
   * You may redirect the user to a proper page telling him that 
   * your application doesn't support multi tab/window. From this page, 
   * the user may decide to go back to the previous page ou loggout in
   * other to have a new session in the current browser's tab or window
   */
  alert('Please go back to your previous page !');
 }
 
}
  1. Add this to your login page
    <script type="text/javascript"> setupWebPage(); </script>
  2. Add this to your other page template
    <script type="text/javascript"> checkWebPageSettings(); </script>
Bigmwaj
  • 361
  • 2
  • 7