How to detect user leaves site? - redux

I'm using react-router's BrowserRouter and Route and Redux. I want to dispatch an action when a user leaves the site or logs out. I'm also using socket.io, but cannot rely on the disconnect because changes in pages within the site cause disconnects.
I looked at window.onbeforeunload and window.onunload, but they also don't work because they get called when I change pages in the site.
All help is appreciated :)

I'm not familiar with React/Redux, but I suspect that its because your client's socket connection is being created within the views that are being created and destroyed. That would mean that you have a persistence problem.
Since Redux is meant for state management, you should store your socket instance there. If your user signs out then you can manually disconnect and discard the instance or if your user leaves your page then it will naturally just disconnect.

Related

How to catch user closed window without logging out of application

My requirement is user should not log in from multiple browser or system simultaneously in application. For this I maintained the flag in database, so whenever user is logged in I am updating flag as yes and when he logged out I am updating it as no.
My issue is if user close the browser window without logging out from application then I am unable to update the flag. So next time when user try to logging in application, It is saying user is already logged in.
I tried using Onbeforeunload event in master page, but whenever I am changing the menu in my application. It is firing that event. For updating the flag I used page methods. But this is not working properly.
I would say, send often via a ajax call to your API that a 'ping' to confirm you are still online. If there is no ping or page change after 3 minutes, I consider the user has been logged off and it sets him as "logged off" in database.
At least, I do this using javascript, but i'm sure you can also in your client-side part of the ASP.NET app you are making.
You can't handle this only by client-side code, using e.g. beforeunload, because the page/browser may be closed for many reasons (e.g. lack of electricity).
What you can do is:
Scheduler on your backend which verifies whether an user did some action since e.g. 1min. In that case you have to update information about user action in your DB after every ajax requests (Hugo Regibo suggested ping requests).
Disadvantage od this solution is this period - when an user turns off the page then he will be not able to log in again for 1min.
Instead of a scheduler you can verify logged-in users (I assume you keep them in a DB table) after each requests.
Use web sockets, you will have continuous connection and you will be notified about closed connection immediately. Disadvantage of this is web sockets don't scale so good as stateless HTTP.
Besides that I don't know whether you use iis with a session provider or not? And when an user closes the page and opens it again should be able to log in with his saved credentials. You should write more of how your project looks like.
I would do it by saving a Session object for each login call. A session ID would then be stored in the user's cookie or authentication token. Each call to the system would validate the user via their session ID. If that session has been invalidated, they just get sent to the login prompt. Whenever the user logs in, it invalidates all of their other sessions.
This way the user could be in their browser on their machine, navigate away, close the browser, and come back to find their session still alive without having to log back in. But, if they log into another machine, then their old session would be invalidated.

SignalR Chat on almost all pages of site

I develop SignalR (1.1.2) chat for our corporative site (ASP.NET) and I don't know how place it for almost all pages of site. I have the next questions:
Online/offline states of users change when users move on other page.
In my chat state setting performs on OnConnected/Ondisconnected callbacks in my Hub class and it call when users move on other page.
Should I initialize SignalR with $.connection.hub.start().done on ALL pages? May be are there workarounds?
What does cross-domain mean? I don't understand this definition.
What logic should I move in OnReconnected callback in my Hub class?
Thanks in advance.
Sounds like you are trying to use SignalR in the wrong way.
You are going to have to start the hub every time you change page unless your application is a single page application. E.g. All run via JavaScript on one page.
When you change page, you are effectively closing down the SignalR connection to the hub, then you will need to start it on the next page. This will raise the Disconnect event.
Each time you connect, your user will be given a new ConnectionID, so their online/offline status will change depending on how you are handling this.
The only work around would be to create a Single Page application.
Cross-Domain means that you are calling the SignalR methods on another URL from the client.
Within your OnReconnected callback you might want to just write some logic that notifys a user that they have been reconnected.

How do I restrict the WCF service called by an ASP.NET AJAX page to only allow calls for that page?

I have an AjaxControlToolkit DynamicPopulate control that is updated by calls to a WCF service. I know I can check the HttpContext in the service request to see if a user of the page (and thus, the control) is authenticated. However, I don't want anyone clever to be able to call the service directly, even if they're logged in. I want access to the service to be allowed ONLY to requests that are made from the page. Mainly, I don't want anyone to be able to programatically make a large number of calls and then reverse-engineer the algorithm that sits behind the service.
Any clever ideas on how this can be done? Maybe I'm over-thinking this?
Thanks in advance.
The simple answer is you can't. The complicated answer is you can fudge it with a lot of work, you could for example
Rate limit based on the IP of the caller.
Drop a cookie based upon the session and rate limit on that.
Drop a cookie based upon the page when the page loads and rate limit upon that.
However none is foolproof, and all can go wrong with legitimate requests.
If you really want to restrict this to just this one server making the request, you could add a certificate to that server and check for that certificate. However, you probably can't really limit access to just a single page calling your service.
You could add a lot of additional elements, like headers etc. - but none will really be totally sound - if someone is determined enough, they'll be able to figure out what you're doing, and replicate that.
So really: why do you need to limit this access this badly?
I solved this with a different approach. Instead of trying to secure the service to a single page, I just secured the service by checking HttpContext to make sure the user making the request is authenticated. This relies on ASP.NET Compatibility being enabled on the WCF service class: http://msdn.microsoft.com/en-us/library/ms752234.aspx
Then I have access to HttpContext within the service and can check that the call came from an authenticated user. =D

Double Logon for some users of an ASP.Net WebForms app

I have an asp .net webforms app that uses forms authentication. For a small number of users we have a problem where they log in, they navigate to a couple of pages and then they are asked to log in again. Once logged in for a second time they seem to be able to stay logged in as expected. They shouldn't be asked to login the second time.
This is a single server, no web farms, nothing tricky.
This only happens to a few users, but it does seem to be all users from the same building. I am unable to replicate this and at this point might even start to deny that t was happening if one of our trainers hadn't watched it happen to a couple of customers.
Has anyone else seen anything like this?
I am also seeing a lot of "Membership credential verification failed." errors in the event log. This may be related, but all the googling I've done seems to point to web farms and the like, not a single server.
UPDATE
There is no proxy server, the IIS server and the browser (IE8) are both on the same machine.
The AV software installed is Symantec Endpoint, on one machine, on the other the user didn't have any AV at all (AV Fail!).
The browser is IE 8 with no frills, not a single addin that didn't come with the default installation.
Both session and user login time-outs are set to 30 mins and the problem happens within 1 min of the user logging on.
Logging shows the user to only have one IP address.
I have tried the sessionMode in all it's variations, this doesn't seem to make any difference.
Something has to be causing ASP.NET to think these users have new sessions or their authentication cookie is getting invalidated. Here a a few things I can think to check:
Are the users accessing the site through a proxy server? One of our customers has a proxy that will sometimes close all open connections causing ASP.NET to see the session as new.
Could an overly agressive anti-virus, anti-spyware product be "eating" the session authentication cookie?
Do they have a cookie manager browser add-in that is causing the authentication cookie to disappear or change?
Sounds basic but I've seen this happen because of site timeouts being set too short. If the user sits on the page for longer than the timeout, they will be forced to logon again. And this could be specific to a page when that page presents a large amount of data that takes a while for them to go through.
One other thing I just thought of, have you allowed multiple worker processes for the ASP.NET process (aka web gardens)? If so, the same constraints as with a web farm would apply for authentication.
Crack open Fiddler from the problem user's PC and see what's getting passed in the headers. My bet is on a proxy server and or networking issue.
Are the users possibly coming from a dynamic ip address? I've seen problems where the users sessions get messed up because the IP address that they're accessing the site from changes for some reason.
Are the people this is happening using a browser that's somehow different (different browser, different version, different extensions)? That could be a clue.
In general, when the problem is somewhat reproducible or at least predictable, I use Http Fiddler. Install it on a client machine, turn it on, and start browsing (this works via a system proxy - so it'll work for firefox, IE and any other proxy-supporting browsers alike). Fiddler will record all http traffic between client and server, and you can then peruse such a session later on to find any oddities.
It's a long shot, but one thing I've seen happen occasionally that can lead to these sorts of unpredictable errors is scripting parallelization issues: sometimes buttons + links have onclick handlers which cause a post-back. If you have several such handlers that fire on the same event - in particular when the default event still fires additionally to your custom onclick or whatnot - you may be causing several postbacks when it appears to be just a single postback. That can cause all kinds of unpredictable weirdness as it's not entirely clear which request ends up "winning" - and some odd errors may cause a session to terminate. Since this behaviour is very browser + network latency sensitive, it seems quite unpredictable when it occurs.
Delete the cookie on the client PC's that are playing up
ASP.NET Forms Authentication can redirect users to the login page if they do not have the credentials to access a specific page. It does this so that users who may have more than one login are given the opportunity to login with another account which may have the appropriate access. Basic question I know, but are the users using the same credentials the second time they log in?
Its possible that you have don't have specifically specified asp.net to use cookie based session but are allowing either cookie or cookieless sessions.
In the later case the session id is embedded in the Url. The type of issues you are experiences might be explained by that. Basically depending on how you define your links, some of them would not get the session id, so the user would get a new session when using those links - or maybe during a redirect. That could explain why at specific parts of your site the users loose their session.
If you have the mixed mode enabled, try setting it to only cookieless and go through your site.
Update: Based on the extra info posted there is surely more info needed for it. Some extra things to check:
Are you using subdomains, if that's the case the cookie might not be configured to allow that and that doesn't fail in all environments.
If you are using in-process session, make sure there isn't a bug in the application causing it to restart the process
Maybe what's causing it to ask for login again is an authorization check, and you have an issue on some roles related code
Is it possible that the user is just opening a separate window? ;)
To rule out the possibility of the browser or a browser addon messing things up, have you checked their User Agent strings? If they are randomly distributed it might not cause the problem, but if they're all the same, this might be a hint too.

in Drupal, how to make login state consistent between browser pages and embedded XMLRPC client?

I have a Drupal site with user logins. Embedded within this site is a Flash application that shows some data to everybody but allows extra functionality if the user is logged on. From within Flash, I'm using XMLRPC to access the system.check method (to determine whether the user is logged in) and the user.login method (to log in a user from within Flash).
Within Flash, everything works fine. However the Flash login state does not seem to correspond to the rest of the site. For example, if I invoke user.login via XMLRPC, subsequent calls to system.check show that I am logged in, but the Drupal user page still says I'm logged out. Or if I am logged in both places and then I log out via the Drupal user page, the next call to system.check still indicates that I am logged in.
How can I make the login state consistent between the Drupal GUI and my embedded Flash app?
(Note: I am not using any XMLRPC library, I am just constructing the requisite XML manually and sending POST methods using a URLRequest object.)
EDIT: I have confirmed via this question and also via testing with a Web Proxy that the SESS cookie returned by the user login page is being picked up and sent back by the flash application.
EDIT: And now I have shown experimentally that even though Flash (via Safari) is sending the same cookie, it gets back a DIFFERENT cookie when it connects to the XMLRPC service than when it requests and HTML page. In other words, Drupal just doesn't support this kind of synchronization and I'm stuck. I'm accepting the answer below that put me on the right track.
EDIT: AMHPHP is not fully released for Drupal6 as of this writing, but it turned out to be installed on the site anyway. Using the DrupalSite library, I was very easily able to log into and out of the site from flash, and the login remained consistent between flash and HTML.
I'm not terribly familar with Flash, but do the URLRequest objects "inherit" state from the browser session, including the user login cookies? If not, you'll need to explicitly send the login cookie with your hand-built request or Drupal will think that it's just coming from another web browser at the same IP address.
If you're not quite sure, using the Firebug plugin might be useful. It lets you inspect any requests that are being piped through the browser, examine their headers, and look at the raw HTTP response object that comes back.
Update: Even more important than the flash widget getting a session cookie is the flash widget getting the SAME session cookie as the web browser itself. Drupal allows users to log in from multiple machines simultaneously, so if the browser is creating one session and the flash widget is creating another, you'd see the behavior you're describing...
It can't be done.
(For details, please see my final edit to the original question and the equivalent information in my comment to #Eaton.)

Resources