how to clear devise session on browser close? - javascript

I am using 'devise' for password authentication in my ruby on rails app. Once I successfully login and I close my browser and open a new browser window I am still logged in. Lets say I am using Chrome, I close all instances of chrome and then open a new one. I am still logged in. The same is the case when I am doing IE and Firefox too.
I would assume on close of window and opening a new window should establish a new session between the server and the browser isn't it? If not how do I achieve that?
i used tried doing clicking on logout button on browser window's onbeforeunload event, but it does not works as it logout of application on any form submit or link click.
window.onbeforeunload = function() {
$('#logout_cls').click();
};
and tried sending AJAX request to the sessions controller destroy action for clearing the session.
jQuery(window).bind(
"close",
function(event) {
$.ajax({
type: 'DELETE',
dataType: 'json',
url: $('#logout_cls').attr('href')
});
});
but all this did not work.

Turns out that the problem was how my session_store was configured.
MyApp::Application.config.session_store :active_record_store,
{:key => '_my_app_session', :secret => '5xb5x1g92e965b95b16e49x79gxx9999', :expire_after => 2.hours}
I removed the options and the issue was solved.
I have another question though and that is removing options does it have any potential risks? I am not storing any important data in the session obviously but putting in data I wouldn't want exposed.
My app would be going live in a few days it would be very helpful to get an answer for this. I googled things for an hour or so but didn't have too much luck.
Thanks

That is actually a feature. Facebook and pretty much all sites with authentication do it through the use of cookies.
Devise's option Rememberable "manages generating and clearing a token for remembering the user from a saved cookie". If you don't want that, then remove the remember_token string and remember_created_at datetime from your user model and remove the Remember Me button from your login page.

Related

Google oauth session lost after page reload (javascript)

I recently moved from the deprecated gapi.auth2 to the new Google Identity Services, using the javascript client library, and noticed a big difference: if someone signs in, and then reloads the page, the session is lost, and has to sign in again, every time the page is loaded. This was not the case with the deprecated library.
The problem can be easily reproduced with the Calendar API example.
Is there any configuration option to keep the session persistent? Or do I need to store the access tokens somehow? I could not find anything relevant in the official docs.
UPDATE:
The migration guide states the following:
Previously, Google Sign-In helped you to manage user signed-in status using:
Callback handlers for Monitoring the user's session state.
Listeners for events and changes to signed-in status for a user's Google Account.
You are responsible for managing sign-in state and user sessions to your web app.
However there's absolutely no information on what needs to be done.
UPDATE 2
To be more specific, the actual issue is not making the session persistent. Managing the sign in state and user session is something I can solve.
The real problem is the access token used to call the Google APIs.
As mentioned in the comments, the access tokens are 1) short lived 2) are not stored anywhere, so even if not expired, they do not persist between page reloads.
Google provides the requestAccessToken method for this, however even if I specify prompt: '', it opens the sign-in popup. If I also specify the hint option with the signed in user's email address, than the popup opens, displays a loading animation briefly, and closes without user interaction. I could live with this, however this only works if triggered by a user interaction, otherwise the browser blocks the popup window, meaning that I cannot renew the token without user interaction, e.g. on page load. Any tips to solve this?
I faced all the same issues you described in your question.
In order to help:
Google 3P Authorization JavaScript Library: in this link we can check all the methods the new library has (it does not refresh token, etc..)
This doc says the library won't control the cookies to keep the state anymore.
Solution
Firstly I need to thanks #Sam O'Riil answer.
As Sam described: "you can somehow save access token and use it to speed-up things after page reload."
Given the the Google's exampe, we should call initTokenClient in order to configure the Google Auth and the requestAccessToken to popup the auth:
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
prompt: 'consent',
callback: tokenCallback
});
tokenClient.requestAccessToken({prompt: ''})
In your tokenCallback you can save the credentials you get somehow, e.g.:
const tokenCallback(credentials) => {
// save here the credentials using localStorage or cookies or whatever you want to.
}
Finally, when you restart/reload your application and you initialize the gapi.server again, you only need to get the credentials again and set token to gapi, like:
gapi.load('client', function() {
gapi.client.init({}).then(function() {
let credentials = // get your credentials from where you saved it
credentials = JSON.parse(credentials); // parse it if you got it as string
gapi.client.setToken(credentials);
... continue you app ...
}).catch(function(err) {
// do catch...
});
});
Doing it, your application will work after the reload. I know it could not be the best solution, but seeing what you have and the library offers, I think that's you can do.
p.s.: the token expires after 1 hour and there is no refresh token (using the implicit flow) so, you will have to ask the user to sign-in again.

Login with AAD MSAL - Login is already in progress

I have a ASP.net website, that uses MSAL to login.
The issue I keep having is that, whenever the user logs in, then logs out again the user is redirected to a logout page.
This page implements the new Msal.UserAgentApplication(msalConfig).logout() function, and redirects the user back to the login page.
This all works perfectly. The login page will then automatically redirect the user back to the AAD login page.
If the user then decides to login again, the result of MyMsalObject.GetAccount() returns null, and an error occurs that mentions the following:
ClientAuthError: Login_In_Progress: Error during login call - login is already in progress.
At first I used one js file to handle log in & logout, I then realised that that probably wasn't he best solution, as it attempted a login on load.
So I decided to split them up into two separate JS files but this hasn't fixed my problem.
msalObject definition:
var msalConfig = {
auth: {
clientId: "my_client_id",
authority: "my_authority_url",
redirectUri: "http://localhost:port"
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true
}
};
var myMSALObj = new Msal.UserAgentApplication(msalConfig);
login code:
$(document).ready(function(){
if (!myMSALObj.getAccount()) {
myMSALObj.loginRedirect(msalConfig);
acquireTokenRedirectAndCallMSGraph();
}
});
Edit:
Some extra details.
I've now made it so that users must click on a button before being redirected to Microsoft to login.
The above unfortunately still applies. After logging in succesfully for the first time & logging out, a secondary login attempt will not yield a value in the function getaccount() even though, it works perfectly the first time.
The error I get after I've logged in is still the same namely:
ClientAuthError: Login_In_Progress: Error during login call - login is already in progress.
Even though I just logged in..
Does anyone have a solution?
Edit 2:
There is a little bit of progress.. sort of, I've been able to fix the error above by changing way I log the user out.
The config file is now a definition within document ready & I've moved the log out function in there aswell.
Although I now face a new challenge..
Refused to display 'https://login.microsoftonline.com/{{}}' in a frame because it set 'X-Frame-Options' to 'deny'.
And im not entirely sure if this is a step forward or backwards. The reproduction scenario remains the same, you log in, then you log out & back in again, when microsoft sends the user back to the login page I get the error mentioned in this edit, but I don't get this error on the 1st login attempt.
The answer stated on: https://github.com/AzureAD/microsoft-authentication-library-for-js/wiki/FAQs#q6-how-to-avoid-page-reloads-when-acquiring-and-renewing-tokens-silently doesn't help at ALL, I'm using chrome but it still doesn't work..
Check session/local storage and cookies for any dangling msal information. We had the same problem, and I stumbled into this link.
https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/1069
It suggests clearing storage and cookies, but if you dig into using your browser tools, you'll see several entries like "msal...interactive...". Those will have values of "in progress", and that's what is causing the error.
Deleting those entries clears up the problem.
First, when using loginRedirect, you need to put the code you want to run when the user is redirected back to your app inside myMsalObj.handleRedirectCallback(callback) instead of inside the function where you initiate the redirect process. Also note, that handleRedirectCallback should be registered on initial page load.
Example:
const myMSALObj = new Msal.UserAgentApplication(msalConfig);
$(document).ready(function(){
myMSALObj.handleRedirectCallback(function(error, response) {
var account = myMSALObj.getAcccount();
if (account) {
// user is logged in
}
});
});
I am a little confused about your app though. Are you saying you have page in your app that just calls myMSALObj.logout()?

How to force logout user when close tab

I am developing a enterprise application using spring and struts. But, i'm getting issue on Tab close. how to force user logging out when close the browser tab or open same page on another tab.
i have been try using onbeforeunload but i am getting issue when application running on mobile browser. and i also have seen following sample but No one has clear explanation.
How to kill session when user closed the browser without logout
How to Detect Browser Window /Tab Close Event?
is there any solution to achieve this problem using javascript or from server?
Thanks
Finally I found a solution that worked!
When the user logs in I use sessionStorage to store that a user has been logged in:
sessionStorage.setItem('logged', true)
SessionStorage will hold that property until the tab or the browser closes.
So inside the application, I check if the SessionStorage still holds that property. If not then I logout the user and I redirect him to the login.
if (!sessionStorage.getItem('logged')) {
localStorage.removeItem('token')
navigator.sendBeacon('api/logout')
window.location.replace("/login") //redirect to login
}
For those who wonder what is navigator.sendBeacon you can read here to learn more. Practically I use it because I want the api/logout to be accessed even if the tab closes.
You may start a ajax request by page onload, and get a tracking session id/serial from server.
Later force all of the requests operations to include the tracking session you just gave to the page using the ajax call above.
If user opens up a new tab, the ajax load starts again. and As far as you check the live session tracks in the server with associated user, you may redirect the user to somewhere else or etc.
I don't think you may rely on onbeforeunload, just the same thing you experience.
As others stated, http is stateless, and cookies and requests are only stuffs you can check the state of the user.
At the server, session cookies could be invalidated by session timeout(if we assume user going to brew some coffee, e.g. it closes the page/tab).
And as explained in above solution, if he/she opens a new tab, the new ajax call might block him/her to perform a new login or etc.
I suggest you may find another solution instead of this approach you are trying to get. It's much easier and more senseful to sync the page state with the last opened page. Let the user opens 5 same page, and just sync them all with each other(simplest solution: refresh others when one gets updated)
You may have a javascript function and invoke it on "onunload" of body and in that script invoke backend code to invalidate the user session.
localStorage can be use to keep idle time for the application with multiple tabs are opened.
// Check browser support
if (typeof(Storage) !== "undefined") {
// Store an item to localStorage
localStorage.setItem("timeIdle", "0");
console.log(localStorage.getItem("idleTime"));
// Retrieve the added item
} else {
//display this message if browser does not support localStorage
console.log("Sorry, your browser does not support Web Storage.");
}
function func(){
$(this).keypress(function(e) {
localStorage.setItem("timeIdle", "0");
});
$(this).click(function(e) {
localStorage.setItem("timeIdle", "0");
});
timerIncrement();
}
function timerIncrement() {
var timeIdle = localStorage.getItem("timeIdle");
timeIdle = parseInt(timeIdle) + 1;
if (timeIdle >= 1) {
logoutCall();
window.location = window.location.origin+"/riskoffice-ui/Login";
}
localStorage.setItem("timeIdle", timeIdle.toString());
}
setInterval(func,1800000); //Runs the "func" function every second

Exchange Information between two windows

Im not sure how to explain my problem in short at the title, so forgive me for this. Lets say I opened my website in some random page, and I have a register button. Really simple, but in my case I require the registration form to appear in other tab(or window). Not "RederPartial", nor popup window of some kind, legit new tab. The problem is, I want to be able do detect, from that random page of mine, when the registration completed (ie a new user has been created). How can I pass this information? without reloading the first page
There are various ways to make two windows talk with each other (through server, with cookies, using FileSystem API or Local Storage.
Locale Storage is by far the easiest way to talk between two windows who come from the same domain, but it is not supported in older browsers. Since you need to contact the server anyway to find out when someone has registered, I recommend using the server (Ajax//web sockets).
Here's a somewhat simple AJAX solution which you could use in your random page:
(function(){
var formOpened = false;
var registered = false;
//Change to whatever interaction is needed to open the form
$('#registerbutton').on('click', function(){
if (!formOpened){
formOpened = true;
//Will try to poll the server every 3 seconds
(function pollServer(){
$.ajax({
url: "/ajax/pollregistered",
type: "GET",
success: function(data) {
if (data.registered){
registered = true;
//do other stuff here that is needed after registration
}
},
dataType: "json",
complete: setTimeout(function() {if (!registered) pollServer();}, 3000),
//will timeout if request takes longer than 2 seconds
timeout: 2000,
})
})();
//opens the new tab
var win = window.open('/registrationform', '_blank');
win.focus();
}
});
})();
You can then use the session key of the visitor in the '/ajax/pollregistered' action to write your backend code to check if and when this visitor registered as user to your site.
If you don't mind using the local storage, you could poll the storage instead of the server and have the registration page write to local storage upon registration. This is less stressing for your server, but might not work for users with ancient browsers.
Also worth nothing that this method of opening a new tab is not completely reliable. Technically there is not a sure shot way of opening a new tab with javascript. It depends on browser and the preferences of the user. Opening a new tab might get blocked for users who are using anti popup plugins.
That being said, I strongly recommend revising your design and try finding a way to work with just one window instead. It's probably better for both yourself and your users.

Other browser windows don't go back to user login page after Meteor.logout()

I have written a meteor application with user login. After a user logs out, the application redirects to the user login page. However, when they are multiple tabs in the browser (or multiple browser windows) where the application is active (and the user is logged in), only the active tab or browser window goes back to the user login page. In the other window it seems the user is still logged in. However, when the user does some further work in the other window, nothing is synced with the db on the server anymore. I thought Meteor.logout() is reactive, so how is it possible that the other browser tabs or windows don't refresh?
I have the folowwing in my router?js file:
var filters = {
isLoggedIn : function(pause) {
if(!Meteor.user()){
this.render('login');
} else {
this.next();
}
}
....
}
Router.onBeforeAction(filters.isLoggedIn);
After pushing the logout button the following js code is executed
Meteor.logout();
Thanks for the help.
Try this:
Meteor.logoutOtherClients
Meteor.logoutOtherClients should log out all sessions. It is designed for situations where the user is logged in on multiple devices and wants to log out on all of them simultaneously.
In my app I didn't want to use a global redirect on logout, but on some templates to redirect to another template if logout happens.
Following Autumn Leonard's comment, I made this work by having the particular template reactive by creating a template.mytemplate.onCreated function and inside there put an autorun function checking Meteor.user() and doing the redirect.
I hope this approach helps others :)

Categories

Resources