I'm implementing Sign in with Apple and noticed that the email
and fullName
properties of the returned ASAuthorizationAppleIDCredential
are only filled on the very first Sign-In for this Apple ID. On all subsequent Sign-Ins those properties are nil.
Is this a bug on iOS 13 or expected behaviour?
Here is the code I'm using to start the request:
@available(iOS 13.0, *)
dynamic private func signInWithAppleClicked() {
let request = ASAuthorizationAppleIDProvider().createRequest()
request.requestedScopes = [.fullName, .email]
let controller = ASAuthorizationController(authorizationRequests: [request])
controller.delegate = self
controller.presentationContextProvider = self
controller.performRequests()
}
I'm receiving the credential in this delegate method:
public func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential else { return }
let userIdentifier = credential.user
let token = credential.identityToken
let authCode = credential.authorizationCode
let realUserStatus = credential.realUserStatus
let mail = credential.email // nil
let name = credential.fullName // nil
}
Seems like a bug but after reading different posts on apple forums it looks like this seems to be the expected behaviour.
So some takeaways.
In case of any connection error with your servers, make sure you save the user details locally (because you are not getting this next time) and keep retrying to create account on your backend.
For testing on device you can revoke your apple ID login for your app. After revoking it will work like a signup next time and you will get the details like (email, name, etc).
To revoke access on your device with IOS 13.
iPhone Settings > Apple Id > Password & Security > Apple ID logins > {YOUR APP} > Stop using Apple ID
In case you're wondering how to retrieve email second and subsequent times, here's a hint: use identityToken which contains encoded in JWT user authorisation data including email.
import JWTDecode
// ...
if let identityTokenData = appleIDCredential.identityToken,
let identityTokenString = String(data: identityTokenData, encoding: .utf8) {
print("Identity Token \(identityTokenString)")
do {
let jwt = try decode(jwt: identityTokenString)
let decodedBody = jwt.body as Dictionary<String, Any>
print(decodedBody)
print("Decoded email: "+(decodedBody["email"] as? String ?? "n/a") )
} catch {
print("decoding failed")
}
Or decode it at PHP backend like this:
print_r(json_decode(base64_decode(str_replace('_', '/', str_replace('-','+',explode('.', $identityTokenString)[1])))));
It is a correct behavior when implementing SignIn with Apple.
This behaves correctly, user info is only sent in the
ASAuthorizationAppleIDCredential
upon initial user sign up. Subsequent logins to your app using Sign In with Apple with the same account do not share any user info and will only return a user identifier in theASAuthorizationAppleIDCredential
. It is recommended that you securely cache the initial ASAuthorizationAppleIDCredential containing the user info until you can validate that an account has successfully been created on your server.
To overcome this issue we can store all the required information in Keychain
. I have created Singleton
class for SignIn With Apple. I am sure it will help you.
Git source: https://github.com/IMHitesh/HSAppleSignIn
You need to follow below steps:
Add the AppleSignIn folder into your project.
Enable SignIn with Apple in
Capabilities
.
Goto your
UIViewController
and Add Container view for SignIn with apple.
if #available(iOS 13.0, *) {
appleSignIn.loginWithApple(view:viewAppleButton, completionBlock: { (userInfo, message) in
if let userInfo = userInfo{
print(userInfo.email)
print(userInfo.userid)
print(userInfo.firstName)
print(userInfo.lastName)
print(userInfo.fullName)
}else if let message = message{
print("Error Message: \(message)")
}else{
print("Unexpected error!")
}
})
}else{
viewAppleButton.isHidden = true
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With