Understanding Firebase Auth Profiles
What happens to your Firebase Auth user record as you use multiple identity providers and make updates?
The docs may be great but the use cases are tricky.
Where does the Profile Info Come From?
The sort of fields that Firebase uses for profile info are
- display name
- email / phone number
- profile pic URL
(That’s enough for now, the rest is largely metadata.)
When a user signs up on a site using the Firebase Client SDK:
firebase.auth().createUserWithEmailAndPassword(email, password)
A record is created within the Firebase Auth database and all that has been provided is the email and password. So of you look at the user record using the admin SDK:
admin.auth().getUser(uid)
the returned UserRecord only has the email field filled in. This is not surprising. You’ll also note that no display name was set because, erm, we haven’t given one yet. You’d need to do that with an update:
var user = firebase.auth().currentUser;
user.updateProfile({
displayName: "Jock Strap"
})
Great. Very simple to understand.
The simplicity is that the user record is given to you as you log in so the cost is minimal. The UI can be updated immediately with contextual user info.
Getting the Profile Info from a 3rd Party
However, if you had signed up using Google auth using the client SDK:
var provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider)
then Firebase has the luxury of pulling profile information from your Google account. This would include your email, display name and profile pic URL. Similarly, other providers might give phone number etc.
Fantastic. Your initial Firebase Auth record gets populated with either the information you provide and set, or that the 3rd party provider supplies.
What is interesting is that when you use a 3rd party identity provider (IDP) then the profile information they hold (the Provider Data) is also available in the UserRecord in a nested list of provider data structures.
This is very handy because it means that if you change your Google profile pic then it doesn’t automatically change your Firebase profile pic but is available to you to copy in (or to “promote” as such), all within the same UserRecord.
You can, for example, update your display name to be something else without affecting your upstream (Google) display name. Similarly, if you update your Google profile pic, it doesn’t automatically update your set Firebase profile pic, but the new URL is there in the Provider Data for you to copy over should you wish.
Manually Creating the Account
You could, of course, create an account using the admin SDK.
admin.auth().createUser({
email: 'user@example.com',
emailVerified: false,
phoneNumber: '+11234567890',
password: 'secretPassword',
displayName: 'John Doe',
photoURL: 'http://www.example.com/12345678/photo.png',
disabled: false
})
In this case, there is not initially any authentication information (Provider) given so the user can’t authenticate until something is linked. Fortunately, this happens the first time a user signs in using the email address matching the record you just created.
Here be a small dragon
Beware though, if you had created a user as above with a set display name of “Jock Strap” and email of “johndoe@example.com” and then signed in using Google, then Firebase will overwrite the display name with whatever Google provided. You would need to go and update it back to Jock Strap.
This seems to only happen the first time a provider is “linked” so is not a big worry but if your use case is to create users in Firebase and then invite them to sign in, you might be surprised at what happens.
Sign in vs Sign Up
If you look at the client SDK, you’ll notice that there is only one “sign up” style call: the createUser listed above. Everything else is signInWith[…].
What this means is that to “register” a new user with, say, a Google account, the sign in procedure acts as a sign up procedure and a user record is create right there and then, using all the profile info grabbed from the 3rd party IdP (Google profile).
The small dragon mentioned above still applies… If you manually create the user and the user signs in (for the first time) using a 3rd party provider, the profile info you specified will be overwritten that first time. Good to note.
Enriching the Profile
You can’t really add fields to the Firebase Auth UserRecord. Yerssss you can set custom claims but that is not what they are for.
You need to enrich the profile with a 1–1 mapping to a database record (possibly Firestore but this is not required). Then your client needs to get the user profile info from Firebase Auth and the extra fields from Firestore before displaying everything to the user.
Should one, in the enrichment record duplicate the email, display name or profile pic? Most use cases I’d say no… join the two records and move on, but there are use cases where you would want to do this. Just be warned that the typical practices and examples available online only assume you’re going to use the Firebase Auth UserRecord to display name, email and pic.
I have found I tend to duplicate the records in order to supply multiple contact email addresses and splitting the display name into parts, nicks etc. This allows me to use the Auth subsystem purely for authentication and the FireStore data for presentation, messaging preferences etc.
This has worked well for me but you are free to choose any pattern you want. They will all work.
Enjoy. Firestore is a very decent solution but it suffers in the community of being put forward as something much more than it purports to be. Firebase Auth is for authentication, not for user record management.