How to unlink Email from Firebase using Firebase Admin Node JS SDK - node.js

I'm trying to unlink Email to the current user that has a Phone Number and Email already linked to it.
here what I do :
admin.auth().updateUser("user uid", {
email: null,
password: null,
})
.then(function(userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log('Successfully updated user', userRecord.toJSON());
})
.catch(function(error) {
console.log('Error removing email:', error);
});
but it was returning error The email address is improperly formatted.
for some reason, only when I remove the email this happen, when i do the same for phone its working :
admin.auth().updateUser("user uid", {
phoneNumber: null,
})
.then(function(userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log('Successfully updated user', userRecord.toJSON());
})
.catch(function(error) {
console.log('Error removing phone number:', error);
});
The above code works, the phone is removed perfectly. but only when I do this to Email occurring error.
Is there something I miss?

UpdateRequest#email must be undefined or a valid email.
UpdateRequest#password must be undefined or an unhashed password.
You may be able to use:
admin.auth().updateUser("user uid", {
email: undefined,
password: undefined,
})
But you are often better off unlinking the EmailAuthProvider credential on the client.
firebase.auth().currentUser
.unlink(firebase.auth.EmailAuthProvider.PROVIDER_ID);

You can unlink providers with the admin sdk using the providersToUnlink
await auth.updateUser(user.uid, {
providersToUnlink: ['password'],
})

Related

Delete a user by email in lieu of UID Firebase

I am successfully deleting accounts with an account UID in a Firebase Function, but is it possible to delete an authenticated account via an email address vs. their UID?
This is what I have now:
admin.auth().getUserByEmail(userEmail).then(function(userRecord) {
// See the UserRecord reference doc for the conteenter code herents of userRecord.
console.log('Successfully fetched user data:', userRecord.toJSON());
admin.auth().deleteUser(userRecord)
.then(function
() {
console.log('This is the ID being used!', userRecord);
console.log('Successfully deleted user');
})
.catch(function(error) {
console.log('This is the ID being used!', userRecord);
console.log('Error deleting user:', error);
});
})
.catch(function(error) {
console.log('Error fetching user data:', error);
});
});
Thank you!
You can use deleteUser(uid) to delete the user account as a second operation after you find the account with getUserByEmail(). The UserRecord it returns has a uid field in it.
So, instead of what you're doing now:
admin.auth().deleteUser(userRecord)
Do this instead:
admin.auth().deleteUser(userRecord.uid)
The admin sdk don't have a method to delete by user so It's not posible to delete user with email. You could use the way that you mention.

How to resolve Mongoose broken authentication

Hey this should be very simple for you nodejs gods, I am trying to make authentication system with nodejs using mongoose so the server is successfully receiving the email and parameters entered in the front-end but it seems as if somewhere in my in my logic I am not doing everything properly can I please get some assistance in handling this error because what happens when I console log on the back-end I get the following.
User Successfully Found
EMAIL: test1#gmail.com
PASSWORD: test1
SIGNINUSER: undefined
I get that User Successfully found even when I entered a wrong user
**Interesting part is when I remove the .then I get back the user object but return errors with regards to unhandled promise
Code below where I am handling the signing in of users
router.post("/signin", async (request, response) => {
const signinUser = await User.find({
email: request.body.email,
password: request.body.password,
})
.then((response) => {
console.log("User Successfully Found");
})
.catch((error) => {
console.log("User Does not exist");
});
//Here I was trying to check if I really am receiving the data from the client
//Just to find that I am receiving the clients data
console.log("EMAIL: ", request.body.email);
console.log("PASSWORD: ", request.body.password);
//Here I was trying to check if the usersInfo is being set inside the siginUser variable
//just to find that I getting the value of undefined
console.log("SIGNINUSER: ", signinUser);
if (signinUser) {
response.status(200).json({
_id: signinUser.id,
name: signinUser.name,
email: signinUser.email,
isAdmin: signinUser.isAdmin,
token: getToken(user),
});
} else {
response.status(401).send({ message: "Invalid Email or Password" });
}
});
Without running the code I would say you are mixing await with then and monoogose queries. So in the proposed solution User.find() returns the query (which is not a promise but a theneable), you exec it to get a promise and await for result. Removing then but keeping your code behavior might look like.
router.post("/signin", async (request, response) => {
const signinUser = await User.find({
email: request.body.email,
password: request.body.password,
}).exec();
if (!signinUser) {
console.log("User Does not exist");
return response.status(401).send({ message: "Invalid Email or Password" });
}
console.log("User Successfully Found");
console.log("EMAIL: ", request.body.email);
console.log("PASSWORD: ", request.body.password);
console.log("SIGNINUSER: ", signinUser);
return response.status(200).json({
_id: signinUser.id,
name: signinUser.name,
email: signinUser.email,
isAdmin: signinUser.isAdm
token: getToken(user),
});
});
I hope it helps.
More info here
Mongoose - What does the exec function do?
Just change your response Code i think this problem will be Gone
return response.status(200).json({
_id: signinUser.id,
name: signinUser.name,
email: signinUser.email,
isAdmin: signinUser.isAdm,
token: getToken(user.toObject()),
});
I changed Only
token: getToken(user.toObject()),

How to change display name in firebase cloud functions?

I am trying to build a firebase cloud function to change a display name.
I know that i can do it easily in android, but since every time i change the display name i need to update all user records and since there isn't seem to be a way to get notified in firebase function when display name has changed (please correct me if i am wrong), i am planning to make the change in firebase and on the same time make the records update.
This is how i started...
exports.changeDisplayName = functions.https.onCall((data,context) => {
console.log(`User ${context.auth.uid} has requested to change its display name`);
//If user not authenitacted, throw an error
if (!(context.auth && context.auth.token && (context.auth.token.firebase.sign_in_provider === 'phone'))) {
if (!context.auth) {
console.log(`User ${context.auth.uid} without auth`);
}
if (!context.auth.token) {
console.log(`User ${context.auth.uid} without token`);
}
if (!context.auth.token.phoneNumber) {
console.log(`User ${context.auth.uid} without phone number (${context.auth.token.firebase.sign_in_provider})`);
}
throw new functions.https.HttpsError(
'permission-denied',
'Must be an authenticated user with cellphone to change display name'
);
}
// Change display display name from data
// update firebase contacts
});
To update a user's name from Cloud Functions, you'll be using the Firebase Admin SDK for Node.js users. Through that, you can update any properties of a user profile with something like this:
admin.auth().updateUser(uid, {
email: 'modifiedUser#example.com',
phoneNumber: '+11234567890',
emailVerified: true,
password: 'newPassword',
displayName: 'Jane Doe',
photoURL: 'http://www.example.com/12345678/photo.png',
disabled: true
})
.then(function(userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log('Successfully updated user', userRecord.toJSON());
})
.catch(function(error) {
console.log('Error updating user:', error);
});

Create users with email an phone provider using Admin Firebase

How can one create a user with phone number and email as providers in Firebase?
The code presented only sets up the phone number as being the only provider.
admin.auth().createUser({
uid: email,
email: email,
emailVerified: true,
phoneNumber: checkMobileTel(mobileTel)
})
.then(function(userRecord: { uid: any; }) {
// See the UserRecord reference doc for the contents of userRecord.
console.log('Successfully created new user:', userRecord.uid);
})
.catch(function(error: any) {
console.log('Error creating new user:', error);
});
I think you are forgetting to add the password field. I hope I could help, happy coding!
password string The user's raw, unhashed password. Must be at least six characters long.

firebase temporarily sending "There is no user record"?

I'm trying to make a simple web application and trying to implement google authentication(login) using passport and store the user in firebase authentication.
So, in the passport middleware what i do is check if the user is authenticated.
if yes then pass the user to the passport.serializeUser(user) else create the user in firebase authentication. and then pass the user to passport.serializeUser(user)
here is a pseudo code -
if (user.authenticated){
done(null, user)
} else {
let promise = {'uid': user.uid, 'name': user.displayName, 'picture':user.photos[0].value};
firebase.auth().createUser({
uid: user.uid,
displayName: user.name,
photoURL: user.picture
});
console.log('i have submitted the user')
done(null, promise)
}
everything is going cool the passport.serializeUser() gets and the user calls done(null, user.uid).
the problem hits when the passport.deserializeUser().
i dont do any fancy there but just get the user from the firebase by using firebase.auth().getUser(id) where it gives me an error.
here is my code for passport.deserializeUser().
passport.deserializeUser((id, done) => { // when we get a request
console.log(`deser id ${id}`); // it shows the id we passed in serialize
firebase.auth().getUser(id).then( // gives an error T_T ?
(user) => {
console.log(`deser data ${user}`); // IT SHOULD GO HERE
done(null, user)
}).catch((error) => { // it goes here and throws an error at me
console.log(`here is the error on deser ${error}`);
// here is the error on deser Error: There is no user record corresponding to the provided identifier.
});
});
the magic happens after some time when the passport.deserealizeUser() gets called again at now for some reason it doesn't throw a error at me.
here is the console log..
i have submitted the user
ser // i do this call in passport.serializeUser()
deser id "someid"
here is the error on deser Error: There is no user record corresponding to the provided identifier.
deser id "someid"
deser data [object Object]
my question is that why does the firebase being delayed?
is it because of the reason that first time the firebase didn't loaded and the second time it loaded and was successful to find the user?
but what could be the reason for that?
any guesses?
Alright guys So, after a big nap I've found out what I did wrong, i wasn't handling the promise from the..
firebase.auth().createUser({
uid: user.uid,
displayName: user.name,
photoURL: user.picture
});
so what i did is like ..
firebase.auth().createUser({
uid: user.uid,
displayName: user.name,
photoURL: user.picture
}).then((user) => {
done(null, user);
});
certainly it requires some time to process the user in the auth() ..
that is why.
ALWAYS USE PROMISES.

Resources