I keep getting a null
email whenever I sign in with Apple. Note that the display name is not null. Also, I've made sure to revoke any tokens before trying to Sign in with Apple again because as per my understanding, Apple only provides the email once, in the initial sign-up. Here is my code for signing in with Apple in Android with Firebase:
The OAuth provider:
fun appleOAuthProvider(appLanguage: String): OAuthProvider {
return OAuthProvider
.newBuilder("apple.com")
.setScopes(listOf("name", "email"))
.addCustomParameter("locale", currentLanguageLocale(appLanguage))
.build()
} //: FUN
Signing in:
private fun singInUser(
auth: FirebaseAuth,
context: Context,
appLanguage: String,
isSigningIn: MutableState<Boolean>,
completion: (FirebaseUser?) -> Unit
) {
auth
.startActivityForSignInWithProvider(context.getActivity(), HelperFunctions.appleOAuthProvider(appLanguage))
.addOnSuccessListener { authResult ->
Log.d("SIGN IN WITH APPLE", "activitySignIn:onSuccess:${authResult.user}")
completion(authResult.user)
} //: ON SUCCESS
.addOnFailureListener { e ->
Log.w("SIGN IN WITH APPLE", "activitySignIn:onFailure", e)
isSigningIn.value = false
completion(null)
} //: ON FAILURE
} //: FUN
After signing in, I collect the user's data with the authResult.user
I previously got:
private fun collectDataFromApple(
user: FirebaseUser?,
completion: (SignInResult) -> Unit
) {
val uid = user?.uid
val email = user?.email
var firstName = separatedFullName(user?.displayName)?.get(0)
var lastName = separatedFullName(user?.displayName)?.get(1)
if (firstName.isNullOrEmpty()) {
firstName = lastName
} else if (lastName.isNullOrEmpty()){
lastName = firstName
}
completion(
SignInResult(
data =
UserData(
personalInformation = UserData.PersonalInformation(
userID = uid,
email = email,
firstName = firstName,
lastName = lastName,
imageBitmap = null,
isNewUser = true,
isEmailVerified = mutableStateOf(true),
firebaseHasData = false
),
addressInformation = UserData.AddressInformation(),
contributeStatistics = UserData.ContributeStatistics()
),
errorMessage = null
)
)
} //: FUN
The user?.email
returns null for an unknown reason. The firstName
and lastName
are not null, however. Why is that?
When you authenticate your users in Firebase using the Facebook provider, the email address of the user is not present inside the FirebaseUser object. So to solve this, you have to read the list of providers and get the second provider as in the following lines of code:
val auth = Firebase.auth
val email = auth.currentUser?.providerData?.get(1)?.email
Do you know why I have to get the second item from the list and not the first one?
The FirebaseUser#getProviderData() method returns an object of type UserInfo which:
Represents a collection of standard profile information for a user. Can be used to expose profile information returned by an identity provider, such as Google Sign-In or Facebook Login.
Typically, the first element (index 0) in the providerData
list corresponds to the user's primary authentication provider which is Google, and the second element (index 1) corresponds to the secondary provider, which, in this case, is Apple, in your use-case.
If you want to have the email present inside the FirebaseUser object as well, then I recommend you update the object using FirebaseUser#updateEmail(email).