Passing email address in custom token - firebase

I have simple backend that can register users and generate jwt's using the firebase-admin package.
When I login with this custom token in firebase console -> authentication the email address is not set. Is there a way to be able to see the email address from there?

You can use the updateUser() method to update the user's email address (detailed docs here):
admin.auth().updateUser(uid, {
email: "modifiedUser#example.com"
})
.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);
});

Related

Firestore permissions inconsistent when user registers

I have Firebase auth set up with email & password, and after the user creates an account, I create a document for the user in Firestore.
It usually works, but sometimes (maybe 10%) the user is created in Auth but not in firestore, with the error code:
FirebaseError: [code=permission-denied]: Missing or insufficient permissions
function registerUser (name, email, password){
firebase.auth().createUserWithEmailAndPassword(email, password).then(function() {
// Registration successful, create firestore document
db.collection("users").doc(email).set({
name: name,
email: email,
level: maxProblemSet,
premium: false
})
.then(function() {
//Success
window.location.replace(myUrl);
}).catch(function(error){
//Registered with auth but not stored in database
alert(error);
});
}).catch(function(error) {
// Handle Auth Errors here.
alert(error);
});
}
My security rules for the users collection look like this:
match /users/{user} {
allow read, write: if request.auth.token.email == user;
}
Is it possible that you are logged in as a different user?
One possible way to debug this is by running the following in the Javascript console in myURL to verify the user identity as seen by Firebase:
firebase.auth().currentUser
If this works as expected, you could try to print the doc in the console to see if the doc is now visible:
db.collection("users").doc(email).get().then(function(doc) { console.log(doc.data()); })

Firebase user.sendEmailVerification() to my own address

Whenever a firebase user creates an account I would like to send the verification mail to my own mail instead of the created user their email.
This is my code:
export function onAuthStateChanged(callback) {
auth.onAuthStateChanged((user) => {
let userinfo = { uid: "", token: "", name: "", email: "", verified: "" }
if (firebaseUser) {
userinfo = {
uid: user.uid,
token: user.ma,
name: user.displayName,
email: user.email,
verified: user.emailVerified
}
if (!user.emailVerified) {
user.sendEmailVerification();
}
}
})
}
And I tried to edit this line:
user.email = "mymail#gmail.com"
user.sendEmailVerification();
But 'user' is read-only
Thanks
Firebase Authentication will only send an email to the account that is specified in the user profile. You can't configure it to send the email elsewhere.
Options I can quickly see:
Either send an additional email to your own a address when you call user.sendEmailVerification().
Or use your own verification flow entirely, not depending on Firebase Authentication's user.sendEmailVerification() method.
Firebase has no specific support for either of these actions, and you'll have to code them yourself as you'd do with any requirement to send email. If you're new to this, you might want to look at using Cloud Functions to send email.

create user with self-specified uid

I am using flutter with firebase to manage my users, and in this link, it says you can specify the uid during user creation: https://firebase.google.com/docs/auth/admin/manage-users#create_a_user
My question: What's the equivalent in dart/ flutter? I understand firebase auto-generates one for you, but in my use case I need to be able to specify mine.
For flutter, I am only aware of createUserWithEmailAndPassword method but it does not have a 'uid' argument.
FirebaseAuth.instance.createUserWithEmailAndPassword(email: null, password: null)
In the link above, however, they provided an example (node.js) with such methods.
admin.auth().createUser({
uid: 'some-uid',
email: 'user#example.com',
phoneNumber: '+11234567890'
})
.then(function(userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log('Successfully created new user:', userRecord.uid);
})
.catch(function(error) {
console.log('Error creating new user:', error);
});
You can fully control the creation of Firebase Authentication users by implementing a custom provider. But as you can probably imagine, this is a sensitive operation, so the code requires that you have full administrative access to the Firebase project. For that reason, you can't run this type of operation in your Flutter app, but must run it on a trusted environment, such as your development machine, a server you control, or Cloud Functions.
Typically this means:
you'll gather the user's credentials in your Flutter app
send them (securely) to a custom endpoint on the server
and there validate the the user credentials are correct
and use the Admin SDK to create a token for the user
that you then send back securely to the Flutter app
There is no such option for any of the Firebase the client SDKs on any platform (Android, iOS, web, Flutter, etc).
Firebase Admin is a server SDK, and trusts that the code calling its methods is privileged and running in a secure and trusted environment. This is considered to be safe for inventing UIDs. The client SDKs are run on user devices, which is considered untrusted and could be compromised. In that case, the Firebase Auth product has to come up with an appropriate UID for the user.
Use the firebase cloud functions
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.createUser1 = functions.https.onCall(async (data, _context) => {
try {
const user = await admin.auth().createUser({
uid: data.uid,
phoneNumber: data.phoneNumber,
disabled: false,
}); return {response: user};
} catch (error) {
throw new functions.https.HttpsError("failed to create a user");
}
});
then request from flutter app
{
"data":
{
"uid": "12345678",
"phoneNumber": "+905378227777",
"disabled": false
}
}

PhoneCredential must be valid phone credential

Hi i'm trying to set the phone number of a User with my following method and I get the following error "updatePhoneNumber failed: First argument "phoneCredential" must be a valid phone credential." I have tried different ways any suggestions?
_addPhone = () =>{
firebase.auth().currentUser.updatePhoneNumber({
phoneNumber: '+441234567890' // Fake for question
}).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);
});
}
The updatePhoneNumber method can only accept valid credentials that firebase will create once a phone number will be verified.
Similar question on the subject

Firebase Convert Anonymous User Account to Permanent Account Error

Using Firebase for web I can successfully create an anonymous user. I can also create a new email/password user. But when trying to convert an anonymous user to a email/password user I get error:
auth/provider-already-linked
User can only be linked to one identity for the given provider.
Firebase documents the procedure here under section "Convert an anonymous account to a permanent account" here:
https://firebase.google.com/docs/auth/web/anonymous-auth
Here's the account link code. Anonymous user is signed in.
return firebase.auth().createUserWithEmailAndPassword(email, password).then(newUser => {
// Credential is being successfully retrieved. Note "any" workaround until typescript updated.
let credential = (<any>firebase.auth.EmailAuthProvider).credential(email, password);
firebase.auth().currentUser.link(credential)
.then(user => { return user; })
.catch(err => console.log(err)); // Returns auth/provider-already-linked error.
});
You should not call createUserWithEmailAndPassword to upgrade the anonymous user. This will sign up a new user, signing out the currently signed in anonymous user.
All you need is the email and password of the user. IDP providers (e.g. Google, Facebook), on the contrary, will require to complete their full sign in flow to get their tokens to identify the user. We do recommend to use linkWithPopup or linkWithRedirect for these, though.
Example:
// (Anonymous user is signed in at that point.)
// 1. Create the email and password credential, to upgrade the
// anonymous user.
var credential = firebase.auth.EmailAuthProvider.credential(email, password);
// 2. Links the credential to the currently signed in user
// (the anonymous user).
firebase.auth().currentUser.linkWithCredential(credential).then(function(user) {
console.log("Anonymous account successfully upgraded", user);
}, function(error) {
console.log("Error upgrading anonymous account", error);
});
Let me know if that works!
After you log in as an Anonymous user, run this code to raise Popup and connect your anon user wit some OAUTH provider
const provider = new firebase.auth.FacebookAuthProvider()
firebase.auth().currentUser.linkWithPopup(provider)
console.log(provider)
For iOS, Swift 5 to create a credential use
EmailAuthProvider.credential(withEmail: , password: )
example:
let credential = EmailAuthProvider.credential(withEmail: emailTextField.text!, password: passwordTextField.text!)
Auth.auth().currentUser?.link(with: credential, completion: { (authDataResult: AuthDataResult?, error) in
// ...
})

Resources