How to detect and prevent user from opening identical web app in more than one tab in a browser

Is there any way we can detect user trying to open more than one instance of a web
application ( in multiple tabs) within a single browser?

If server and clients Ares in the same network check if the ip address of client is alteady connected

i have the record of connected IPs.
But how to force Xojo web application not to open another window ( in another tab ) when there is already a tab with the same app in the same browser instance.
E.g if i have web application A, i do not want the user to be able to open
2 Chrome tabs each containing / connecting to web application A.

Cookies seem to be a reasonable way to achieve this.

Create a new WebPage that will be shown whenever we want to prevent the user to access the application (I gave it the “NotAllowedWebPage” name in this example).

Then, add this new method to your Session class:

Public Sub EnsureOnlyOneTabIsAllowed()
  // This is the identifier each browser tab will be assigned
  Var currentIdentifier As String = Self.Identifier
  
  // The identifier we are storing in the browser, shared between every tab
  // and window of the same browser
  Var storedIdentifier As String = Session.Cookies.Value("identifier")
  
  // The session granted to access the application
  Var sessionWithStoredIdentifier As Session = App.SessionWithIdentifier(storedIdentifier)
  
  If storedIdentifier = "" Or sessionWithStoredIdentifier = Nil Then
    // Store a cookie in the browser
    Session.Cookies.Set("identifier", currentIdentifier, DateTime.Now.AddInterval(0, 0, 1))
    
  ElseIf storedIdentifier <> "" And sessionWithStoredIdentifier <> Nil And storedIdentifier <> currentIdentifier Then
    // That instance isn't the one with granted access
    If Self.CurrentPage <> Nil Then
      Self.CurrentPage.Close
    End If
    
    NotAllowedWebPage.Show
  End If
End Sub

Now you can use this method whenever you need it, for example, in the WebSession.Opening event.

Also, implement the WebSession.UserDisconnected event:

// We'll ask the framework to destroy this session as soon as possible
Self.Quit

You’ll probably have to adapt the code to your needs and think about edge cases, but I think this method could work.

4 Likes

If your users have accounts, then this is easy to do - when a new session opens and a user logs in, you can simply check if they have any other sessions open, and decide what to do. In my web app, if the user logs in a second time, the first session is closed with a warning message “you can only be logged in once”.

For anonymous users the problem is much more difficult. You can’t always rely on IP addresses because of NAT and CGNAT which means some users from the same service (e.g. Verizon, ATT) may appear to be on the same IP.

I will try Ricardo’s solution once i am back at in front of PC
Mike, according to your solution, what would happen if the user intentionally log in with 2 different user account on the same browser but in different tab panel? this can crash the server i think. Your solution works well if user log in from two different browser ( or more )

I’m not sure what you mean - nothing about this should crash the server. Two different tabs in the same browser would give each session the same cookies, whereas 2 different browser apps would not share cookies, but otherwise WebSessions in xojo are isolated from each other.

My application renders dashboard based on user setting.
i have one user who has the habit of opening two instances of the app in a single browser. one for setting the dash board ( Tab 1 ) and one for rendering the dashboard ( Tab 2 ) . Maybe it is due to my bad design, but sometimes , ( not all the time ), when he does that the software ( the web app ) crashes. both instances in the different tabs connect to a remote database for storing the data.

I want to prevent this behaviour ( multiple tabs )

If your users are connected using a username (login), you could iterate thru all sessions and, for the ones on which the given user is logged, somehow disable the UI (e.g. put a modal dialog saying “Please close the Settings tab before continuing here”). And that session could also stop rendering things.