Multiple tabs same session, clear the session when all tabs are gone - javascript

So I recently had acceptance criteria for a site I was building that went as such:
After a user logs in to the site in any tab if they navigate to the site in a new tab they must already be logged in
When a user logs out of any tab they must log out of all tabs immediately
A user can refresh the page and stay logged in
Once all tabs are closed the user is logged out and must log back in
I didn't have access to change the server code (so this had to be done on the client)
I found this Question/Answer which was really helpful
When looking through this I had to rule out cookies because outside of doing a request to the server tab A will no know that tab B had changed the cookie
So I took some parts of the answer from the question above and started using local-storage and added an event to check for if the 'logged-in' state was changed which allowed me to log out in one tab and immediately log out in another without using setInterval to continuously check! Yay
But then I still had the issue of once all tabs were closed if you opened a new tab and navigated to the site you were still logged in.
I tried some possible solutions like having a counter of the tabs that has a session open, decrement and increment on tab close/open (using window.onbeforeunload). ISSUE: refresh of the site when there is only one tab active would log you out. Everything I could think of had an edge case where it didnt work.

local-storage + session-storage!
I would store the value logged-in in both the local-storage and the session storage, when a window was loaded (either a new tab or a refresh of the existing one) it would check local-storage for the 'logged-in' value and if it was not there it would check session-storage!
Basically I am using session-storage to handle the refresh of a page and local-storage to handle multiple tabs. Each time a window/tab is unloaded (closed or refreshed) I delete the local-storage 'logged-in' and when I come back into the page if it is in session-storage but not in local-storage I put it back into local-storage from the session-storage and continue as an authenticated user
Here is the code for this:
On login:
localStorage.setItem('logged-in', true);
sessionStorage.setItem('logged-in', true);
In my base component:
window.onbeforeunload = (event) => {
localStorage.removeItem('logged-in');
}
let loggedIn = localStorage.getItem('logged-in');
let sessionLoggedIn = sessionStorage.getItem('logged-in');
if(!loggedIn) {
if(sessionLoggedIn) {
localStorage.setItem('logged-in', JSON.parse(sessionLoggedIn));
//go to authenticated space
window.location.href = '/authenticated';
} else {
//go to login
window.location.href = '/login';
}
} else {
//go to authenticated space
window.location.href = '/authenticated';
}
window.addEventListener('storage', (event) => {
if (event.key == 'logout' && event.newValue) {
sessionStorage.removeItem('logged-in');
localStorage.removeItem('logout');
window.location.href = '/login';
}
});
On logout
localStorage.setItem('logout', true)
Hope this helps some of you if you ever find yourself in a similar situation

Related

How to hide a div after showing only once in a session

I've a div that will show the success message after successful login and will hide after 4 seconds. The js code used is
document.getElementById('success').style.display = 'none';
}, 4000);
This works fine. But this div will pop up every time I navigate to home page and I don't want that to happen. This div should be in hidden state until logged out and logged in again. It would be better to have a solution that wont use jquery as this is a project. I've tried sessionStorage also but that hides the div immediately after showing and not lasting 4seconds.
Thanks in advance
const alreadyShown = localStorage.getItem('alreadyShown');
if (alreadyShown === 'true') {
document.getElementById('success').style.display = 'none';
}
setTimeout(() => {
localStorage.setItem('alreadyShown', 'true');
document.getElementById('success').style.display = 'none';
}, 4000);
you can use js localStorage. localStorage is similar to sessionStorage, except that while localStorage data has no expiration time
You can do something like this:
To check if user has successfully logged in. you can set a key/value pair in session storage after successful login. we will delete this key/value pair when we logged out from the website.
So when user redirects to home page the first thing we will do it check if "loggedIn" key is there in session storage or not.
const isLoggedIn = sessionStorage.getItem('loggedIn');
if(!isLoggedIn) {
document.getElementById('success').style.display = 'block';
setTimeout(() => {
document.getElementById('success').style.display = 'none';
sessionStorage.setItem('loggedIn', true);
}, 4000);
}
So now on first time user redirects to home page then the success message will be displayed and the "loggedIn" key will be set to session storage. if user redirects back to home page there will be key so we will not display message.
now all you need to do is to delete this "loggedIn" key from the session storage whenever you logged out.
You can delete the key by
sessionStorage.removeItem('loggedIn');
now the key is deleted after log out. it will display success message on successful loin for the first time.
Make display to none by default and toggle to block when required
You can achieve your required behavior by reversing your implementation.
Set display to none by default
Convert to block after clicking login and authentication
Set a timer for 4 seconds ( to display the login message )
Set display back to none.
document.getElementById("app").style.display = "block";
setTimeout(
() => (document.getElementById("app").style.display = "none"),
4000
);
Click here for complete code snippet
to make sure it world on any browser old and new - those who do and those who do not eat cookies, those who keep session storage and those who don't want them.
You need to start your page with the display: "none" of your 'success' element, and only show it, if it's the first session page load.
/message/.test( name ) ? 0 :
success.style.display = "block",
name = 'message';

How to determine whether the user closes browser tab or refreshes the page

I am building a two person game app using vue.js. The app uses vuex for state management and Firestore as the backend server.
If the user leaves the app by either closing the browser tab or navigating away, the games Firestore files need to be deleted. However, if the user refreshes the page, the Firestore files need to remain so that the reload process can repopulate the game.
So I need to determine if the user has refreshed the page as opposed to closing the browser or navigating away.
As shown below, in vue's created lifecycle I setup a "beforeunload" event Listener and also start my Firestore listeners
created() {
// This window event listener fires when the user
// navigates away from or closes the browser window
window.addEventListener("beforeunload", (event) => {
const isByRefresh = getUnloadInitiator();
if (!isByRefresh) {
this.stopFirestoreListeners("beforeunload");
}
// Cancel the event. This allows the user to cancel via popup. (for debug purposes)
event.preventDefault();
event.returnValue = "";
// the absence of a returnValue property on the event
// guarantees the browser unload happens
// delete event["returnValue"];
});
this.startFirestoreListeners("created");
},
The getUnloadInitiator function is shown below. This is where I need help. Right now all this function does is console.log various performance values.
function getUnloadInitiator() {
// check for feature support before continuing
if (performance.mark === undefined) {
console.log("performance.mark NOT supported");
return false;
}
console.log("===============================");
// Yes I know that performance.navigation is depreciated.
const nav = performance.navigation;
console.log("nav=", nav);
console.log("===============================");
// Use getEntriesByType() to just get the "navigation" events
var perfEntries = performance.getEntriesByType("navigation");
for (var i = 0; i < perfEntries.length; i++) {
var p = perfEntries[i];
console.log("= Navigation entry[" + i + "]=", p);
// other properties
console.log("type = " + p.type);
}
console.log("===============================");
performance.mark("beginLoop");
const entries = performance.getEntries({
name: "beginLoop",
entryType: "mark",
});
const firstEntry = entries[0];
console.log("firstEntry.type=", firstEntry.type);
console.log("===============================");
//TODO: Determine how unload was initiated
return true;
}
Below is the output from my console.logs. They are the same for refreshing the page, closing the browser tab, or navigating away. All show "reload" as the navigation type.
===============================
nav= PerformanceNavigation {type: 1, redirectCount: 0}
===============================
= Navigation entry[0]= PerformanceNavigationTiming {unloadEventStart: 25.399999976158142, unloadEventEnd: 25.69999998807907, domInteractive: 633, domContentLoadedEventStart: 633, domContentLoadedEventEnd: 633, …}
type = reload
===============================
firstEntry.type= reload
===============================
Any help on how to differentiate between refreshing the page, closing the browser tab, or navigating away would be appreciated. There must be away, because the native cancel browser popup I'm using for debug purposes differentiates between fresh and browser tab close.
Thanks
You can use a source of authority as persistence, be it firestore, local storage, or cookies. you are able to get the browser's tab ID with tab.id and compare it to an existing one should one exist.
browser.pageAction.show(tab.id);
Source: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Working_with_the_Tabs_API

How to detect if the user is logged in to redirect to a specific page javascript

I'm currently building an app which requires to login first. Login page is called using
function onDeviceReady() {
navigator.splashscreen.hide();
window.open("http:website_login_link", "_blank");
}
since that website's login page needs to be opened first when the app is launched (because only certain people are allowed to login). After login, the user is brought to the website, but I want the user be able to see other features of the app. Thus, I want to redirect to a specific page after the user is logged in. I want to set isLoggenIn = true after the user has been logged in. And then call
if (isLoggedIn == true){
window.location("home.component.html"); // welcome page
}
But I don't know how to detect when I should set isLoggenIn = true, since I'm not storing credentials manually. So, how and when can I set isLoggenIn = true ?
window.location = "http:website_login_link";
Two method
1. window.location = "Your website"
2. location.href="Your website"

Google+ login via Sign In button: Trouble with persisting session across different pages, and displaying Login/Logout buttons

My page /login.php displays the signin button and signs you in. So far I have managed to:
Include relevant code in common files so that G+ signin code is present in all pages
Moved stuff from the button element itself to tags in the header
Instead of keeping any significant logic in my signinCallback, I attached a callback function that is called on each page load, like this:
po.src = 'https://apis.google.com/js/client:plusone.js?onload=OnLoadCallback';
I then made that function look like this:
function OnLoadCallback(){
var sessionParams = {
'client_id': 'myapp-id-here',
'session_state': null
}
gapi.auth.checkSessionState(sessionParams, function(stateMatched){
if(stateMatched === true){
console.log("You do not seem to be logged in!");
}else{
console.log("You should be logged in!");
// Trigger request to get the email address.
gapi.client.load('plus','v1', loadProfile);
if(window.location.pathname === '/login.php'){
toggleElement('signin-button');
window.location = "/";
}
}
});
}
I found this bit of code regarding the session state in some article but I'm not sure it works as it's supposed to. In Chrome it seems more or less OK but in FF, when I first tried it, it should give me "not logged" in my console. Since I was logged in FF with my google account (but not in my app!), it seemed to recognize me as logged in, or at least my session was anything but the null (as stated in the code).
So, what should I use instead of "null" when it comes to determining session state?

How to block simultaneous user login from different tabs in the same browser

My application uses spring3 mvc, I want to redirect the user to the same page if the user open two tabs & try to login simultaneously using different userId's .
Like the gmail functionality, if two users login from two different tabs the first user will get logout & see a session timeout message.
Several tabs of the same browser use the same session, so if you just forbid access to the login page to already logged in users, this situation should never happen.
The only possibility to do that is if cookies are not supported by the browser, and the container falls back to URL rewriting to maintain sessions. In this case a user could have two simultaneous sessions in the same browser. But in this case, you could simply force the usage of cookies for your webapp.
Try below attached code.
While clicking on Login Set A Key in Local Storage with some key (Example 'Y'). Place the Below Mentioned in Common File which will be available in entire application. The Below Event will be Triggered when the Value of the Local Storage is Changed. when the Value is Y. Call Logout Function. After login clear the Local Storage.
While Clicking login - > CLEAR_USER_SESSION - > Y - This will Logout other Session's of the Same Application in the Same Browser as per the Below Code.
After Login - Change the Value to N or Empty - CLEAR_USER_SESSION - > 'Y' or ''
window.addEventListener('storage', function(event) {
if (event.key == 'CLEAR_USER_SESSION') {
var winUrl = window.location.href;
var terminateSession =event.newValue;
var homepage = "N";
if(document.getElementById("empTrId")){
homepage = "Y";
}
if(terminateSession && terminateSession.trim() == "Y" && !winUrl.includes("loginAction.do?method=logout")
&& !winUrl.includes("login.jsp") && homepage == "N"){
logout();
}
}
});

Categories

Resources