ASAuthorizationAppleIDRequest with name and mail scope returns nil values

喜欢而已 提交于 2020-04-29 07:05:18

问题


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
}

回答1:


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.

  1. On the first time sign in with apple (signup) make sure to create user account on your backend.
  2. 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.

  3. 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



回答2:


This seems to be the expected behaviour:

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 the ASAuthorizationAppleIDCredential. It is recommened that you securely cache the initial ASAuthorizationAppleIDCredential containing the user info until you can validate that an account has succesfully been created on your server.

Source https://forums.developer.apple.com/thread/121496#379297




回答3:


In https://developer.apple.com/documentation/signinwithapplerestapi/authenticating_users_with_sign_in_with_apple it says:

Because the user’s information isn’t shared with your app in any subsequent API calls, your app should store it locally, immediately after you receive it from the API response. In case of subsequent failures in your process or network, you can read the information from local storage and try processing it again.




回答4:


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 the ASAuthorizationAppleIDCredential. 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:

Step:1

Add the AppleSignIn folder into your project.

Step:2

Enable SignIn with Apple in Capabilities.

Step:3 -> IMPORTANT

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
}



回答5:


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.

  1. Import this library to decode JWT: https://github.com/auth0/JWTDecode.swift
  2. try this code
    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
       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])))));


来源:https://stackoverflow.com/questions/57593070/asauthorizationappleidrequest-with-name-and-mail-scope-returns-nil-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!