Account onLogin hook Meteor loop - javascript

I am building an application using Meteor. I want to create a new Cart ID (to act as a cart where I can store items) each time a user logs into my application. However, every time I open a new page in the application, a new Cart ID is created. Does this mean that the application "logs in" every single time I click on a new page in the app? Here's my code:
Accounts.onLogin(function(user){
var newCartId = uuid.new()
Meteor.users.update({_id: user.user._id}, {$set: {'profile.cartId': newCartId}})
console.log('just created a new Cart ID at ' + Date());
});

Yes, this is true.
Every time you open a new page you are not logged in. When the localStorage token authenticates you, similar to how a cookie does, you are logged in automatically. This hook will also run when you are logged in automatically.
Its difficult to define how a user logs in. Meteor's onLogin hook fires on any type of login Method.
You can customise when you want your hook to run, though:
Accounts.onLogin(function(info) {
if(info.methodName == "createUser") {
console.log("This user logged in by signing up");
}else if(info.type == "password") {
console.log("This user logged in by using his/her password");
}else if(info.type == "resume") {
console.log("This user logged in using a localStorage token");
}
});
So here you can make the event fire only when a user logs in using his or her password. Or even when they sign up. You can use this to exclude running your hook if the user opens a new page, which uses the localStorage token to sign up.

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");

Firebase user's details change listener in Javascript

so if a user logs into your app, you can check that by
firebase.auth().onAuthStateChanged((user)=>{});
but if the user is already logged in and his user has a property change, how do you see that?
in my case, I have the user verify his email address and when done, he should be able to see a change instantly on his app after verifying his email. So I am using react native, which is pretty much javascript with ES6 syntax in it and I am doing a firebase.auth().onAuthStateChanged(); but its not working, I even have a button on the screen that checks if verified like this:
if (!firebase.auth().currentUser.emailVerified) { firebase.auth().currentUser.sendEmailVerification(); }
else if (firebase.auth().currentUser.emailVerified) { this.setState({ showVerifier: false }); }
but even that isn't working, as if the firebase.auth().currentUser doesn't update if the email is verified, what can be done here?
As far as I understand your question, I would like to give you an idea.
I think onAuthStateChanged() gets triggered only when your Auth State Changes (login, logout) and not when the user properties change.
As they have mentioned in the documentation,
Adds an observer for changes to the user's sign-in state. Prior to
4.0.0, this triggered the observer when users were signed in, signed out, or when the user's ID token changed in situations such as token
expiry or password change. After 4.0.0, the observer is only triggered
on sign-in or sign-out.
function isVerified(){
var user = firebase.auth().currentUser;
if(user != null){
var status = user.emailVerified;
if(status)
{
// Verified
}else{
// Not Verified
}
}
else{
// User didn't login!
}
}
So, you have to manually check it by defining a function like above and you can call this function when the user clicks the button
If you are using react-native-firebase (highly recommended, since it is supports the latest firebase features), you can listen on user changes as stated in this doc
From the doc
Adds a listener to observe changes to the User object. This is a superset of everything from auth#onAuthStateChanged, auth#onIdTokenChanged and user changes. The goal of this method is to provide easier listening to all user changes, such as when credentials are linked and unlinked, without manually having to call User#reload.
onUserChanged(listener: AuthListenerCallback): () => void;

How to get User Details after Google Authentication in web app using firebase?

I have a web-app that allows users to sign in using their gmail account.Once the user is signed in, I am able to see it's details using result.user object like this-
function signInWithGoogle(){
var provider=new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider).then(function(result){
var user=result.user;
console.log("user_provider="+user.displayName+" user_email="+user.email+" user_dp="+user.photoURL+" user_verification="+user.emailVerified+" uid="+user.uid);
}).catch(function(error){
console.log("error="+error);
});
}
After signing in, I want to keep user details in page even after reloading and refreshing for that I used User object of auth() like this-
$(document).ready(function(){
var user=firebase.auth().currentUser;
console.log(user);
});
But it's showing user as null although I can see user email address in authentication console in firebase.
P.S. I have also used onAuthStateChanged instead of currentUser , but still it's not working.
onAuthStateChanged should work. You have to listen to it correctly.
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// currentUser should be available now.
} else {
// No user logged in.
}
});
Keep in mind that the state is stored in single host origin web storage. So if you navigate to a page with a different domain, the state will not propagate.

Meteor.user() is null when trying to check user login status

I am trying to show other some user's profile page to non-logged in and logged-in users. The problem is that whenever I check
if(Meteor.user() === me)
Meteor.user() returns null and code crashes since no one is logged in. How can I check whether there are logged in users?
Try this and let me know:
if (Meteor.user()) {
// code for login user
} else {
// code for non-login user
}

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