Limit Only One Session Per User In ASP.NET Mvc 4 - javascript

I am working on one web application in which i want to make sure that website allow only one login per user at a time.
when user login i am updating table column islogged=1 when logoff i am updating islogged =0
but the problem is when user session timeout or if user closing browser i am unable to capture this events.i am using sqlserver state to store sessions so Session_End event is not fired in this state .
it only works in InProc State. and also in browser close event i have tried onunload event. but this event is fired on tab closed also. not able to differentiate tab close and browser close.
i want only one concurrent user login. is there any other way to achieve this.
i am using this code to capture browser close event.
<body class="fixed-top" onclick="clicked=true;" onunload="CheckBrowser()">
<script type="text/javascript">
var clicked = false;
// var xmlHttp
// var browser = navigator.appName;
function CheckBrowser() {
debugger
// var browserClose = isUserClickedCloseButton();
if (clicked == false) {
$.ajax({
url: "#Url.Content("~/Account/LogOff")",
type: 'Post',
success: function (data) {
},
error: function () { alert("Error On Logut..."); }
});
}

alternatively you can store store session id in DB along with the current loggedin status as true or false. when user hits just check if loggedin flag is true and take the action needed

Please check the below links which has similar Q&A.
Only one concurrent login per user in Asp.net
Only one concurrent login per UserID in Asp.net

Related

How to logout a user when a new user logs in in the same browser?

I'm facing this problem where I have two dashboards for two users, one is admin and the other is a merchant. The problem is when admin logs in and in the new tab a merchant logs in too. If I refresh the admin page I get a navbar that is meant for merchant and the rest of the page is of admin... I'm storing the token in localStorage.
Can anyone tell me how I can logout the previously logged in user, If a new user logs in in the on the same browser?
If you need to log out in the other tabs it would help to pass the signal between multiple tabs you can use a local storage event.
Set a logout-event on the previous tabs
localStorage.setItem('logout-event', 'logout' + Math.random());
Every other tab will listen it with the the code below.
window.addEventListener('storage', function(event){
if (event.key == 'logout-event') {
// your code here
}
});
Simply put whenever a merchant logs in using a new tab follow the above procedure to logout any other user.
Instead using localStorage, you should use sessionStorage when you want the token to be unique to each tab/session and to be deleted when tab is closed for ex
U can use sessionStorage Instead of localStorage:
look at this:
https://hashnode.com/post/how-to-handle-multi-user-login-in-same-browser-cjbxct3yq06mk4cwty2bmpsn1
If you ignore IE, I prefer using Broadcast Channel API instead of localStorage event
Init your broadcast channel and listen the event
const bc = new BroadcastChannel("your_channel_name")
bc.onmessage = (e) => {
// Business logic here
// data sent through the channel is available at e.data
}
When you want to trigger the event
bc.postMessage("your logout message");

Refresh page on new user sign in when using Google oAuth 2.0

I'm trying to make a website using Google Sign For Websites. Mostly just for the sake of learning about how it works.
I've followed the steps outlined in that tutorial Google Provides which works fine. Users can successfully sign into my site, it is able to pass the users ID to the backend and then verify the ID server side using a php script.
Php then creates a session for the user on the website. What I can't figure out is how would I refresh the page when a user clicks the Google Sign in button and the sign in is successful. Refreshing the page would allow the home page to be reloaded with the new php session data.
<div class="g-signin2 signin-button" data-onsuccess="onSignIn" data-theme="dark"></div>
function onSignIn(googleUser){
// The ID token you need to pass to your backend:
var id_token = googleUser.getAuthResponse().id_token;
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://mywebsite.com/tokensignin.php');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
console.log('Signed in as: ' + xhr.responseText);
};
xhr.send('idtoken=' + id_token);
};
I've tried using simply location.reload() inside of the onload = function() portion of the code. This causes the page to just infinately refresh every time it is loaded however since Google verifys that the user is signed in through this xhr variable every time.
I've tried looking through their reference to use GoogleAuth.isSignedIn.listen(listener) to monitor any changes but it doesn't seem to fullfull what I want it to or I'm not using it correctly since I don't exactly know what the listener should be.
The other option might be to use their GoogleAuth.attachClickHandler(container, options, onsuccess, onfailure) function but I'm not entirely sure how the properly configure the options field/variable.
If someone could provide some insight as to how this world work I would greatly appreciate it.
To summarize if the user is already signed into my website using Google I want the page to do nothing, if they click the signin button, after the sign in is successful I want to refresh the page they are on.
You could add a listener to xhr with a callback function.
xhr.addEventListener("load", loginComplete);
And then create a function:
function loginComplete(evt) {
console.log("Login Complete");
window.location.reload();
}
EDIT:
Ok. Since the listener doesn't help. You will need to check if the user is already logged in. To save that information one thing I could think of would be using cookies.
So you could store the Auth Token you receive from Google and set a cookie for it and check everytime before you make your POST.
Here is a nice js cookie library: https://github.com/js-cookie/js-cookie
Then onload you save the id:
xhr.onload = function() {
Cookie.set('google_token', id_token);
window.location.reload();
};
And the onSignIn function would be like:
function onSignIn(googleUser){
var cookie = Cookie.get('google_token');
if(cookie != undefined){
//cookie is set
return;
}
...
//rest of the function
}
Of course you need to improve this code, for example, check if the token stored in the cookies is still valid, some cases you can just refresh it instead of making the user log in again (the oAuth API provide such things).
Make some security measures to be sure the token is not being injected and etc..
My approach was the same as yours and I indeed ran into the same problem with constant refreshing.
I tried a couple of solutions, the best working one was as follows:
User signs in using GAPI2 triggering callback onGoogleSignIn
Backend checks ID token validity, and signs user in through session on my webapp
If successful, I log the user out using GAPI2, preventing infinite reload, because onGoogleSignIn is never called again
Then I refresh the page and replace the sign-in button with a logout button for my webapp
This solution is of course pretty much useless if you want to manipulate some data on user's Google account, but I found no use for this functionality.
Code for signing someone out of their google account.
function signOut() {
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
}
Why not have your back end redirect (or send info so the page so it can redirect on success)?
What is the need for reloading the login screen?
You could also check out the listener documentation it seems like this may solve what you want. ie. listen for user change and trigger a function or redirect.
https://developers.google.com/identity/sign-in/web/listeners

onbeforeunload to rollback some actions

I have an onbeforeunload and it is working fine. However, I wanted a way to trigger my DB method to delete my existing item if the user choose to leave the page. How is it possible to detect the result as well as to trigger my DB method? My DB method is on the server-side.
Here is my javascript for the onbeforeunload:
var showMsg = true;
window.onbeforeunload = function () {
if (showMsg) {
return "You must publish your profile. Leaving this page will delete the profile information you have entered."
}
}

How to prevent the loss of form data when session expires?

QUESTION
Using ASP.NET VB and/or JavaScript how can a user be prevented from losing form data when a session expires?
The Problem
Currently when a user is filling out form data for a period longer than the session timeout period all form data is lost on post due to session expiry.
Client side actions such as typing DO NOT reset the session timeout period.
Ideas
I would like to know ways to prevent this problem occurring.
My initial idea is a notification message warning of pending expiry
and an option to reset session timer.
An alternate idea is a way to pass a key press or mouse movement to the server to cause an auto refresh of session timer.
SOLUTION 1 : KEEP SESSION ALIVE
On way of to solve your problem is to keep session alive while the form is opened. I'm sure there many ways to 'keep alive' user's session. For me, I use generic handler and this work fine at least in my requirement.
First, create a generic handler and enter code as below:
Public Class KeepSessionAlive
Implements IHttpHandler, IRequiresSessionState
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Session("KeepSessionAlive") = DateTime.Now
End Sub
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Make sure your generic handler class implements IRequiresSessionState as above.
Then in you form page, use jQuery.post to post request the above handler at time interval of you choice. For example:
<script type="text/javascript">
$(function () {
setInterval(function () { $.post('<%= ResolveClientUrl("~/KeepSessionAlive.ashx")%>'); }, 10000); ' 10 secs interval
});
</script>
While user is on the form, the POST requests will keep refreshing user's session just like normal page requests and therefore, IIS will keep on reseting the session timeout.
SOLUTION 2 : ALERT USER BEFORE TIMEOUT
Another way is to alert user when session is about to end. This can be achieved simply by using plain javascript alone. I used this method few years back so pardon my scripting.
Create a javascript method :
function sessionTimeout(n) {
setTimeout("alertSessionTimeout()", (n - 1) * 60 * 1000);
}
function alertSessionTimeout() {
var answer = confirm("Your session is about to expire in 1 minute.\n\n
Click 'OK' to extend your session.\n
Click 'Cancel' to terminate you session immediately.");
if (answer == true)
window.location = location.href;
else {
window.top.location = 'logout.aspx';
}
}
On your form page, just enter onload script on your body tag:
<body onload="sessionTimeout(<%=session.Timeout %>)">
So, if your timeout setting is 10 minutes, user will be alerted on the 9th minute. Of course, you might want to change the code when user click OK button. My code above will refresh the page and that definitely not what you want to do, or else, user's data will be lost. You can use the generic handler as in SOLUTION 1 above to reset the session and call sessionTimeout again to reset client side timeout countdown.
In the age of single page apps if you need to work with old school approach, my advise would be to create Ajax request that constantly updates data in your website or just checks for session expiration (probably request itself would prevent that). But if it happens and you receive session expired message you could just show some login popup for user to login without leaving actual page.

Facebook client side authorization flow and get access_token for all scenarios like when scope for an app changes, etc

I am trying to do 3 simple things using JS thru a client side authorization flow :
Check if the user is logged in. If not, display the login dialog with proper scope.
If user is already logged into Facebook on the browser, then ensure the app has been authorized (if not, display the Authorize dialog).
If user has already authorized the app then ensure that the access_token on the authResponse has the right scope (permissions) required by the app. (if not, redisplay the authorize dialog for the new permissions).
I am trying to leverage js sdk for this, without wanting to write any hand-coded dialog's etc, since the sdk handles the browsers/devices nuances automagically.
I could not find this properly described anywhere either on FB documentation or otherwise. (no documentation around the fact that the permissions/scope for the app can change post authorization).
Thanks you in advance.
After an arduous attempt I have this working and here are the steps to do this with the minimum amount of code.
*The Approach *
Use fb-login-button to facilitate login. Login Button is the only thing that is displayed when the user first arrives on the page. All other forms are 'hidden', forcing the user to click on this button before being able to go forward.
setup onlogin="function();" on the fb-login-button - so that you can hide the login-button and display the rest of the forms/etc for the user to proceed on your app. Please note that onlogin is called only once (either when the user logs in or authorizes the app with the new scope) - so it is safe to always hide the login-button and display the remaining of the page/form for the user to proceed.
The most important step : use the same fb-login-button to also do the authorization with the right scope : so even if the user is logged in - force the user to click the login-button. fb-login-button in this case, will check if the scope of existing access_token (for already logged in fb user), is a subset of that requested on the fb-login-button attribute. fb-login-button will display the authorize dialog for you automatically in this case. In any case the onLogin callback is triggered (when the login-button should be hidden() and the remaining page/forms be shown()).
Subscribe to the FB.events to get the authResponses and the corresponding access_token every time it is set, which happens 2 times :
a. When the fetch is first displayed for already logged in user
b. After the user authorizes the app first time or second time with the new scope.
This allows you to keep the authResponse and access_token fresh to be used for all subsequent graph calls/etc..
*Implementation Steps *
fb-login-button must be created with onlogin callback :
<div class="fb-login-button" onLogin="onLogin();" scope="publish_actions"
data-size="large">Use This App</div>
Please note that the text does not say Login, but 'Use this App', since the button is displayed for authorization in addition to just logging in.
Subscribe to the Events.
// authRepsonse Change is needed when the user hits the UseApp button
// and permissions are re-fetched - then a new token needs to be refreshed
FB.Event.subscribe('auth.authResponseChange', handleResponseChange);
// when the user logins and all permissions are all set, clicking on the
// use-app will not do anything and authResponse will always be null.
// so this subscription is necessary
FB.Event.subscribe('auth.statusChange', handleResponseChange);
Login Function to hide Login button and display form.
function onLogin () {
hideLogin();
showMain();
}
Handle Status Changes to save Token.
// global variable that contains the access_token
// for use in graph calls/etc.
var authResponse = null;
function handleResponseChange(response) {
if (response && response.authResponse) {
authResponse = response.authResponse
if (response.status == 'connected') {
updateUserInfo(response);
return;
}
}
else {
authResponse = null;
}
hideMain();
showLogin();
}
Hope this helps and I believe that this is probably the most optimal way of handling client side authentication flow without doing any extra authorization/login dialog and let FB sdk do the trick.

Categories

Resources