Meteor log out do not sync between tabs - javascript

I am using Meteor with React and is facing a problem on log out function. When I open more than 2 tabs on the same browser, If I logged out from one tab then the other opening tabs would not be logged out but will be hang if I using it. There are only 2 ways to log out: close the tab or refresh it.
I try the same for log in function and it worked, log in status is synced between all opening tabs.
My current code to call the log out function:
signOut: function(event) {
event.preventDefault();
Meteor.logout();
this.props.history.pushState(null, "/");
},
Thank for the helps.
Update:
I checked the websocket, it's seem that the server did send the logout status but my client code did not call the logout method (or it is hang). Then every data in the hang tab is still existing. But I don't know how to check further more.

I found the cause. It was because I try to avoid sending data on Meteor.publish() if users is not logged in. The problem is I do not return anything on that case.
My solution is return this.ready() when the user is not logged in like this:
Meteor.publish("myCollections", function (){
if (!this.userId) return this.ready();
return MyCollections.find({owner: this.userId});
});

From the meteor documentation, you can use Meteor.logoutOtherClients() before calling Meteor.logout().

Normal (as in non-incognito) browser tabs share the same session resume token. The Meteor server will update them all when the user status changes for the associated session.
It is possible to reactively track the login status using 2 reactive calls:
Meteor.userId() - return the user's id or null if no user is logged in.
Meteor.loggingIn() - returns true if the user is currently in the transient state of logging in and false otherwise.
The status may take a few seconds to update across tabs, but it will happen eventually. It is up to you to detect those changes and act upon them.
You can easily test this by running the following reactive code in the consoles of 2 open tabs connected to the same Meteor server:
Tracker.autorun(function() {
if (Meteor.loggingIn()) {
console.info('logging in');
} else if (Meteor.userId()) {
console.info('logged in');
} else {
console.info('logged out');
}
});
Try to log in and log out from one of the tab and watch the other follow along.
Using this technique, you could track the login state and change your application state and do something accordingly (e.g, redirect/render a different view or layout) when the login state changes.

Related

Keep user logged in in app even after the app closed using Async Storage

I am trying to maintain a user as logged in, in an app even after the app closed, which means the user will no longer need to re-enter his/her userID and password again everytime he/she opens the app.
I want to achieve this using AsyncStorage (other than redux), my question is: is it possible to do so using AsyncStorage? I found sources online on how to persist data using Async but U could not connect those with what I wanted to do.
You should do it this way:
User opens the app, may be do this in you splash screen's didMount i prefer these kind of things to be done before hand in the splashsreen only. Check a flag in AsyncStorage say isLoggedIn if thats true, fetch
user credentials from the AsyncStorage and fed them to your login
request and the rest of the app flow continues.
If isLoggedIn is false (or null), show login screen to the user and upon successful login, save the credentials to AsyncStorage and on success must save the isLoggedIn flag to true and rest of the app flow continues.
For point 1, the code should look like:
AsyncStorage.getItem('isLoggedIn').then((value) => {
if(value && value === 'YES') {
//hit login api using the saved credentials and take user inside the application.
} else {
//Take user to login page and progress with point 2.
}
});
and below is the code that should work for point 2 upon success of login.
const encrypted_username = myFancyEncrptionFunction(username);
const encrypted_password = myFancyEncrptionFunction(username);
AsyncStorage.setItem('username', encrypted_username).then(()=>{
AsyncStorage.setItem('password', encrypted_username).then(()=>{
AsyncStorage.setItem('isLoggedIn', 'YES');
});
});
Its totally upto you how you want your user's credentials to be saved in AsyncStorage i.e. with or without encryption. But its always recommended to keep such things encrypted.

Java script, PHP

I have a scenario where I need to execute a logout function in php, this function deletes the user from DB and informs another application through sockets. This function should be called when the user closes the browser or tab. I have tried various scenarios posted by others and nothing seems to work in chrome(Version 57.0.2987.110) and firefox.
Following is the examples I tried along with links,
My sample Code
<script type="text/javascript">
var str = 'delete';// this will be set to 'Apply' if the form is submitted.
function logout(){
location.href = 'Logout.php';
}
function pageHidden(evt){
if (str==='delete')
logout();
}
window.addEventListener("pagehide", pageHidden, false);
</script >
Examples I tried....
// 1st approach
//window.addEventListener("beforeunload", function (e) {
/// var confirmationMessage = "Do you want to leave?";
// (e || window.event).returnValue = confirmationMessage;
// return confirmationMessage;
// });
// 2nd approach
// window.onbeforeunload = myUnloadEvent;
// function myUnloadEvent() {
// console.log("Do your actions in here")
// }
// 3rd approach
$(window).on('beforeunload', function() {
return 'Your own message goes here...';
});
checked the following urls
1. window.onunload is not working properly in Chrome browser. Can any one help me?
2. https://webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/ - I followed this approach. Tried some other approaches as well.
3. I can't trigger the unload event in Chrome etc....
Any help is much appreciated, because if the user closes the browser an entry remains in the DB and this is not allowing any new user to login.
You shouldn't rely on JavaScript for sever-side code. It's actually entirely possible to achieve what you're looking for, purely with PHP. Just make sure to 'kill' the session before starting it:
session_set_cookie_params(0);
session_start();
session_set_cookie_params(0) will tell the browser that any exisiting session should only exist for another 0 seconds. Essentially, this means that a user will automatically 'log out' immediately. This way, you don't have to rely on client-side code, which is susceptible to all measure of interrupts such as power outages.
Hope this helps! :)
The correct way to logout is related to how they are logged in.
In PHP, the login state is typically managed by sessions. By default the timeout is 24 minutes of inactivity, but you can easily reduce it.
When a user logs out, you typically reset one or more session variables, and, while you’re at it, kill off the current session, and delete the session cookie.
However, you cannot rely on a user to log out, and many typically just wander off. This is why there is always a relatively short timeout on sessions.
If you want to automatically logout when the tab is closed, you will need JavaScript to intercept the process with window.onbeforeunload and then use Ajax to send the logout to the server.
As regards the database, you normally do not record the login state in the database. You may record the login time, and if you like, the logout time, but remember that may be never.

In Meteor, how/where do I write code that triggers when an authorized user has logged in?

New to Meteor, I'm using the alanning:roles package to handle roles.
I've managed to be able to only publish a collection when a user is logged in, when the page is first refreshed.
Meteor.publish('col', function(){
if (Roles.userIsInRole(this.userId, 'admin')) {
console.log('authed');
return Sessions.find({});
} else {
console.log('not auth');
// user unauthorized
this.stop();
return;
}
});
Logging out kills access to the collection (I'm using mongol to see). Logging back in after logging out, or logging in from a logged out state when the page is first loaded, will not give me access.
The webapp I'm trying to build is something like an ticketing system. I'm trying to be secure, so no unnecessary publishing if the user is not authorized.
What I'm trying to do is, get ticket information submitted from users from a collection, and display it on the client screen (as long as the client is authorized first). Maybe a better way to handle this is to force a refresh (how do I do that?) after a user change so unauthorized users are "kicked" out? And render all relevant data from the private collection right after the user is authorized?
I actually managed to get what I want for now with helpers...
In my ./client/Subs.js file:
Meteor.subscribe('col');
Template.NewTicket.helpers({ // match the template name
// move this into method later, not secure because on client??
isAdmin() {
console.log('is admin.');
console.log(Meteor.userId());
Meteor.subscribe('col');
return Roles.userIsInRole(Meteor.userId(), 'admin');
},
});
and then somewhere in my template file ./client/partials/NewTicket.html:
<template name="NewTicket">
{{#if isAdmin}}
{{/if}}
</template>
to trigger the check? I'm 99% sure theres a better way.

Simple form submission with Firebase; can I detect when offline?

I'm using Firebase perhaps slightly unconventionally -for simple form submission. Submission of my website's contact form simply results in:
ref.push({name:'dr foo', email:'1#2.com', message:'bar'}, myCallback);
The Firebase is hooked up to Zapier to send the site owner an email. All works well, but I'd like to be able to handle the user loosing their connection. When Firebase can't reach the server I'd like to display: "Please check your connection", or a similar message when the user hits the send button. The "Thanks, we'll be in touch"-type message should only be displayed on a successful write.
At first I tried including an if (error) branch in the callback, but of course disconnection is not something that Firebase considers an error as it "catches up" when it can.
I also tried the code in the docs which monitors .info/connected. While this wouldn't display a message on a form submission attempt, I was thinking I could instead display a warning if disconnected. The sample worked intermittently (Chrome 39, Firefox 30, Linux Mint), but the lag between disconnection and the event firing means it's probably not suitable for this case.
Is what I'm trying to do possible?
It indeed seems that the .info/connected values only changes once some other data transfer occurs (and fails).
The only way I can come up with is by using the transaction mechanism with applyLocally set to false. E.g.
function testOnlineStatus() {
var ref = new Firebase('https://your.firebaseio.com/');
ref.child('globalcounter').transaction(function(count) {
return (count || 0) + 1;
}, function(error, committed, snapshot) {
if (error) {
alert('Are you offline?');
}
}, false /* force roundtrip to server */);
}
setInterval(testOnlineStatus, 2000);
This one triggered for me after about 15 seconds.

FB.logout() - no access token - "Log in as Different User"

This question is in relation to this question: FB.logout() called without an access token
I had a question i was hoping someone could help with.
I get everything in the link above, but how do you handle when someone uses a public computer and leaves themselves logged in to FB by accident? Then a new user tries to log in to an app, but it is not them. I want to have a button to log them out of FB altogether to "log in as a different user".
I cannot do that until they authorize the app, right? So they need to authorize the app under someone else's account and then log out? There has to be another way.
Any feedback would be great - tried searching for a while on this, but to no avail. I might be over thinking it, but there should be some way to "log in as a different user".
You can do something like:
FB.getLoginStatus(function(response) {
if (response.status === "connected") {
FB.api("me", function(response2) {
// notify the user he is logged in as response2.name, and if it's not him call FB.logout
}
}
else {
// prompt the user to login
}
}
Modify your logout to something like this :-
function logout(response){
console.log("From logout" + response);
if(!response.authResponse){
window.location = "/web/login/";
return;
}
FB.logout(function(response){
FB.Auth.setAuthResponse(null,'unknown');
logout();
});
}
i.e keep on sending logout request to Facebook till the actual logout happens.
Try to use Session and save the user's ID in that session.
You can control the expiration time of that session( by default its 20 minute if the user doesn't have any activity on the page)
then in each page Load even check whether the season is still active for that user or not.
page Load event:
if(Session["LoggedIn"]==null)
{
Response.Redirect("~/Login.aspx");
}
This code above will redirect user to login page of your website if the session has expired.

Categories