invertase / react-native-apple-authentication

A React Native library providing support for Apple Authentication on iOS and Android.
Other
1.4k stars 223 forks source link

Identity Token Generated on iOS Does not Have Email #284

Closed thecodecafe closed 2 years ago

thecodecafe commented 2 years ago

Hi, please I've been trying to figure this out for some days now, please when I use this library to log in on iOS the identity token appears to be missing the user's email (masked or unmasked), wanted to confirm if there's an extra step required to get the user's email.

After JSON decoding one of the identity token on iOS I don't get the following.

{
    "aud": "[bundle ID]",
    "auth_time": 39853984,
    "c_hash": "[a hash]",
    "exp": 1654811770,
    "iat": 1654725370,
    "iss": "https://appleid.apple.com",
    "nonce": "[a nonce]",
    "nonce_supported": true,
    "sub": "[the sub]"
}

Please does anyone know how to get the email address on subsequent calls without depending on the email gotten from the performRequest call?

mikehardy commented 2 years ago

FAQ 1 https://github.com/invertase/react-native-apple-authentication#faqs

Apple only returns the full name and email on the first login, it will return null on the succeeding login so you need to save those data.

It sounds like you are not saving the data, though the API is designed in such a way that you need to be saving the data. Have you tried saving the data on the first login call?

thecodecafe commented 2 years ago

Hi @mikehardy, yes we save the user information but the issue is during our Pilot test we had a scenario where after the apple log in the user was not able to proceed because when our app was about making a call to the api with the credentials generated from apple login, a network error occurred, this caused their email to be missing the next time they tried apple log in we're trying to see if it's possible to keep getting the email to prevent this from happening in production. Funny thing is Android is always returning the email address.

mikehardy commented 2 years ago

@thecodecafe oh that is most unfortunate. I'm not sure how that could be avoided actually - networks must never be relied on. Makes me think of a different angle though: you could use async-storage locally to store "the things I needed from the sign in" plus the "have I transferred this successfully to the servers?" state, and proceed accordingly?

To be clear, I'm just brainstorming here. My app would fail in this scenario too and I would never have thought of it.

There was information about decoding the token and it is/was supposed to contain the email address, but that was on android (as you mention) and the posts talking about decode for iOS look similar to what you saw. So with regard to what the token is supposed to be for, it's not vital the email is in there, so perhaps they issue it slightly differently depending on platform (native API calls via Obj-C for iOS vs REST API calls for Android)

thecodecafe commented 2 years ago

@mikehardy your first proposal about storing the email is actually a good idea, we're actually doing that now.

We were also able to find a fix to this edge case, since the email is always available in the identity token payload for apple auth on the web, we decided when this happens we will simply ask users to log in with apple on our web app and then continue back on the mobile app when they are done there, this works for us because in a scenario where the user's sign up with apple auth is complete we don't rely on the email anymore we simply use the sub in the identity token to find the associated user and log them in so long as the identity token provided is valid.

Also I noticed that after we implemented this I went to https://appleid.apple.com and removed our app from my Apple ID log in apps and to my surprise the email is now always present in the identity token on iOS, not sure if this was initially a glitch from Apple, I'm still monitoring to see if anything changes but so far it's been good.

Thanks for your quick response by the way, I really appreciate it, i'll be closing the issue with this comment.

mikehardy commented 2 years ago

I like that solution best of all, as with async-storage there is still the chance - even if smaller now - that the login succeeds on the apple server side but you don't even get the response to store it locally. I think your solution, even if it is a little "heavy" for the users, is probably the only 100% certain way - try another method (web) where you can get the email every time and proceed accordingly. Thanks for sharing it - good luck with your project!

Filippo39 commented 8 months ago

@thecodecafe Hi, I wanted to know if the email is always present in the identity token received from the performRequest call or not (both ios and android). I'm asking you why you were monitoring the situation and perhaps you also have some feedback for the apps in production. Thanks in advance.