I have been having trouble getting the display name out of Firebase.
below is the Sign Up process coding
const promise = auth.createUserWithEmailAndPassword(email, pass)
.then(
(user)=>{
// here you can use either the returned user object or
firebase.auth().currentUser. I will use the returned user object
if(user){
user.updateProfile({
displayName: textUsername.val(),
// photoURL: // some photo url
})
}
})
.then( function() {
console.log('User Name Set!')
})
.catch(function() {
console.log('error')
});
promise.catch(e => console.log(e.message));
})
firebase.auth().onAuthStateChanged(firebaseUser => {
if(firebaseUser) {
console.log(firebaseUser)
} else {
console.log('not logged in');
}
})
the console.log shows 'user name set!' and the console.log(firebaseUser) shows that the displayName is set in the database of the currentUser, and the name is what i expected.
However,
console.log(firebase.auth().currentUser)
gives null, and
if (user != null) {
console.log(user.displayName);
}
this also returns as null.
I have been looking for ways to get the data of the firebase dataset but I cannot manage to do that.
it will be great if anyone can give me any advice about it.
Thank you.
firebase.auth().currentUser.displayName returns the OAuth provider's display name. However, firebase.auth().currentUser resolves asynchronously and is empty/null for a moment on page load. If you put the console.log(firebase.auth().currentUser.displayName) inside the .onAuthStateChanged you'll see that.
I ended up using recursion to solve this. I wish there was a more elegant way but this was the only thing that worked for me. Please share if you have solved this with a different solution!!
I needed this for creating new users. When someone signed in it never seems to return null.
The setTimeout() slows the recursion down by .5 seconds so that you don't get an error by calling the function too many times. You can speed it up or slow it down by adjusting the milliseconds.
Working code:
auth.onAuthStateChanged(user => {
if (user) {
// Everything inside here happens if user is signed in
console.log(user)
// Greet the user with a message and make it personal by using their display name
injectDisplayName = () => {
if(firebase.auth().currentUser.displayName === null){
console.log('happens');
setTimeout(() => {
injectDisplayName()
}, 500)
} else {
document.getElementById('display-name-header').textContent = `Hello, ${firebase.auth().currentUser.displayName}`
}
}
injectDisplayName()
} else {
// Everything inside here happens if user is not signed in
}
})
Related
I am working for a task related to react native app based user management. After they successful sign up themselves as a user, I include a data which is store Boolean value and I have named it as emailVerifiedAccount (this is the stored data if they registered themselves successful and indicate if they are a verified user if they click on email verification link send to them). In login screen I would like to check the Boolean value that I get from firestore in onAuthStateChanged and only direct them to index screen when the emailVerifiedAccount that I get is return true. Code below is authstatechanged for login screen .
const onAuthStateChanged = (user) => {
if (user) {
checkEmailVerifiedAccount=firestoreService.isEmailVerifiedAccount(user);
try {
if(checkEmailVerifiedAccount===true){
navigation.navigate('Index');
}else{
Alert.alert(
"Verify as a Playbookx user",
"Please click on email verification link send to your email. If you do not receive any email ,please contact user support",
"You may come back to login again after you verified your email",
[
{ text: "OK"}
]
)
}
} catch (error) {
console.log(error);
}
}
};
and in firestore.js is where all the code and function that is related with Firestore database. isEmailVerifiedAccount is one of the class object which checking verified user using email.
isEmailVerifiedAccount = async (user) => {
return await firestore()
.collection('users')
.doc(user)
.get()
.then(snapshot => {
if (snapshot.exists){
const user=snapshot.data();
const emailVerifiedAccount={
emailVerifiedAccount:user.emailVerifiedAccount
};
return emailVerifiedAccount
}
})
.catch(error => {
console.log(error);
});
};
And the problem that I facing right now is that, it lead me to index screen when the emailVerifiedAccount in Firestore is false. Picture below is the structure for Firestore.
Your isEmailVerifiedAccount function is asynchronous, so when calling it you have to await the result:
checkEmailVerifiedAccount = await firestoreService.isEmailVerifiedAccount(user);
const checkEmailVerifiedAccount = firestoreService.isEmailVerifiedAccount(user);
checkEmailVerifiedAcccount seems to be an object but you are checking if it's equal to true. Either return user.emailVerifiedAccount directly from isEmailVerifiedAccount function or read that property like this:
const checkEmailVerifiedAccount = firestoreService.isEmailVerifiedAccount(user);
if(checkEmailVerifiedAccount.emailVerifiedAccount) {
navigation.navigate('Index');
}
I'm struggling to see why some code is behaving as it is.
Vue3 front end login page interacting with Google Firebase services (authentication and firestore db)
const onSubmit = () => {
.
.
.
// above missing section just gathers some form data
signInUser(form_email.value, form_passowrd.value)
.then(() => {
const user = firebase.auth().currentUser
if (user.emailVerified) {
checkUser(user.uid)
router.push({ name: 'Profile' })
}
else {
resendVerification.value = true
commandNotification('show', 'error', 'Unverified Account')
}
})
.catch((error) => {
if (error.code === 'auth/invalid-email') {
commandNotification('show', 'error', 'Invalid Email Address')
}
// followed by other checks
})
}
signInUser is the official firebase auth email and password sign in function that is imported into this module.
So, user is signed in, then I check to see if the user has verified their email address. If they have I do some further checks in a "users" firebase table, and then route user to their profile page.
The problem that I am having is that the router.push is happening before the check user function has completed. I've even put a 10 second setTimeout between the two lines and the router push comes immediately.
It seems checkUser is running asynchronously but I didn't think it was. I've not marked it async myself.
The checkUser function itself does the following
const checkUser = (userid) => {
db.collection("users").doc(userid).get()
.then((d) => {
if (d.exists) {
userStateStore.action(MutationType.user.updateUser,
{
id: d.data().id,
country: d.data().country,
handle: d.data().handle
}
}
else {
// user creation when they do not exist
}
})
}
I'm currently testing with a user that already exists. Because the route is being called immediately the profile data is not in the vuex store.
I'm looking for some pointers on how to approach debugging this, or an answer if you see a specific problem.
Many thanks in advance.
checkUser is async. It should return the promise that get() returns...
const checkUser = (userid) => {
return db.collection("users").doc(userid).get()
// ...
I'd cleanup the caller (without async/await) like this...
const onSubmit = () => {
return signInUser(form_email.value, form_passowrd.value)
.then(() => {
const user = firebase.auth().currentUser
return user.emailVerified ? checkUser(user.uid) : Promise.resolve(false)
}).then(checkUserResult => {
if (checkUserResult) {
router.push({ name: 'Profile' });
} else {
resendVerification.value = true
commandNotification('show', 'error', 'Unverified Account')
}
})
// ...
These could also be made tidier (and exactly equivalent) using async/await syntax.
It seems checkUser is running asynchronously but I didn't think it was. I've not marked it async myself.
Yes, .get() is asynchronous and even though you haven't used async/await you're instead using .then().
One solution could be to put the router.push() invocation within the callback of the .then() within checkUser().
i have this issue with a firebase app i'm also developing , my intentions are to create an user and update his profile with a name using the firebase method createUserWithEmailAndPassword.
I evolve the process and eventually it works but also throws an error which says kind of :
Uncaught TypeError: Cannot read property user of undefined
at eval (index.js?xxxx)
at e.g (auth.esm.js?xxx)
at kc (auth.esm.js?xxxxx)
at gc (auth.esm.js?xxxxxx)
at B.k.Zb (auth.esm.js?xxxxxx)
at Qb (auth.esm.js?xxxx)
despite of having already modified the user info, then i need to refresh the page to get this error to dissapear.
Here part of my code:
signUserUp({ commit }, payload) {
commit("settingLoader", true);
firebase
.auth()
.createUserWithEmailAndPassword(payload.email, payload.password)
.then(() => {
let user = firebase.auth().currentUser;
console.log(user);
user
.updateProfile({
displayName: payload.name
})
.then(usermod => {
const User = {
id:usermod.user.uid, undefined usermod
email:usermod.user.email, undefined usermod
name:usermod.user.displayName undefined usermod
};
commit("settingUserIn", User);
commit("settingLoader", false);
});
})
.catch(error => {
console.log(error);
commit("settingLoader", false);
});
}
Then the error does reference to an eventual undefined "usermod" for user.uid, user.displayName ,and user.email.
Any advice about what i'm missing?
thanks in advance!!
https://firebase.google.com/docs/reference/js/firebase.User#updateprofile
Firebase's user.updateProfile method returns a void promise, meaning it returns a promise with no value.
You still have access to your user variable in your then, so why not just change it to
...
user
.updateProfile({
displayName: payload.name
})
.then(() => {
const User = {
id: user.uid,
email: user.email,
name:user.displayName
};
commit("settingUserIn", User);
commit("settingLoader", false);
});
...
Currently, when the user goes through the Social auth (via redirects), it successfully creates a user under Firebase Authentication, but fails to retrieve the Google/Facebook API's data. Perplexed as to how it's failing to retrieve the data when the Auth is successful.
I used to only have the SignInWithPopup (which works perfectly fine), but am trying to get getRedirectResults to work too (for mobile).
Given the behavior I've been seeing, the problem is most likely with the getRedirectResults. Most likely not the social API setup, because otherwise the user would never get created in Authentication.
The following code resides in componentDidMount (this is a React.js app):
if (this.state.device === 'mobile') {
firebase.auth().getRedirectResult().then(function(result) {
console.log('login successful! Data is:');
console.log(result);
if (result.credential) {
var provider = result.credential.providerId;
self.handleSocialAuth(provider, result);
}
}).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
});
}
results is supposed to contain the user's data, keeps returning:
login successful! Data is:
{user: null}
I have not deviated from official docs examples, which is why I'm confused.
firebase.auth().getRedirectResult() - is called after the page loads.
Official doc link: https://firebase.google.com/docs/auth/web/google-signin
Use the below method to retrieve the user that is logged in.
firebase.auth().onAuthStateChanged(function(user) {
console.log(user);
});
If no user is logged in the user will be null.
Live example:
checkAuthStatus(){
firebase.auth().onAuthStateChanged(user => {
this.setState({ btnWithImg: user });
if(user !== null){
this.setState({ userIsLoggedIn: true });
this.props.toggleLogIn();
}
});
}
You should call firebase.auth().getRedirectResult() only when user has been authenticated. Example
firebase.auth().onAuthStateChanged(user => {
if (user) {
const result = await firebase.auth().getRedirectResult();
assert(result.user, 'user is empty')
}
});
I'm makeing tests with Firebase Authentication from javascript client and I'm trying to retrieve the idToken with retrieve id tokens on clients documentation
I think I'm forgetting something basic.
A user is logged in with Google
The code is just i've seen in other posts and in the documentation. And the result is in the comments.
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log(user); // this is shown. Firebase user and provider data
console.log(user.uid); // Shown
firebase.auth().user.getIdToken().then(function(idToken) {
console.log(idToken+'--'); // Nothing happens. No errors and the function not continues
});
console.log(user.uid); // Nothing happens
}
})
Thanks
EDIT:
if I add anything wrong nothing happens too. for example if I add an alert it shows the alert but if I have a mistake, for example alter() not shows any error. Added catch and nothing too
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
alter() // Nothing happens and the function stop
console.log(user); // this is shown. Firebase user and provider data
console.log(user.uid); // Shown
firebase.auth().user.getIdToken().then(function(idToken) {
console.log(idToken+'--'); // Nothing happens. No errors and the function not continues
}).catch(function(error) {
console.log(error+'--'); // Nothing
});
console.log(user.uid); // Nothing happens
}
})
firebase.auth().user doesn't have the user in that moment yet. You have to use the user from firebase.auth().onAuthStateChanged directly like this:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log(user); // It shows the Firebase user
console.log(firebase.auth().user); // It is still undefined
user.getIdToken().then(function(idToken) { // <------ Check this line
console.log(idToken); // It shows the Firebase token now
});
}
});
You can only use firebase.auth().user after firebase.auth().onAuthStateChanged is completed and outside of its scope, otherwise it will be undefined.
firebase.auth().currentUser is synchronous. We can make it asynchronous by subscribing to the auth observable instead.
Depending on the library we’re using, the JavaScript SDK has onAuthStateChanged() and AngularFire2 has both authState() onAuthStateChanged().
// For AngularFire:
private afAuth: AngularFireAuth,
afAuth.authState.subscribe(user => {
if (user) {
user.getIdToken(true).then(idToken => {
// ...
});
}
});
// or
this.afAuth.auth.onAuthStateChanged(user => {
if (user) {
user.getIdToken(true).then(idToken => {
//...
});
}
});
// For the JS SDK
firebase.auth().onAuthStateChanged(user => {
if (user) {
user.getIdToken(true).then(idToken => {
// ...
});
}
});
For firebase versions greater than V8. We directly have to call the functions of auth.
const loginWithGoogle = () => {
const googleProvider = new GoogleAuthProvider();
signInWithPopup(auth, googleProvider)
.then((userCredentials) => {
if (userCredentials) {
setIsUserAuthenticated(true);
window.localStorage.setItem('authorization', true);
console.log(userCredentials);
userCredentials.user.getIdToken().then((token) => {
setToken(token);
console.log(token);
});
}
})
.catch((err) => {
console.log(err.message);
});
};