Flutter苹果登录 - 邮箱为空

18
我正在尝试使用apple_sign_in包将“Apple登录”添加到我的Flutter iOS应用程序中。代码大部分都能正常工作。我的问题是,对_firebaseAuth.signInWithCredential(credential)的调用会创建一个具有空标识符的Firebase帐户(请参见下面的截图)。关于这个问题的一件奇怪的事情是,当用户在注册时选择共享他们的电子邮件地址时,在调用AppleSignIn.performRequests()后,result.credential.email包含用户的电子邮件地址。因此,我真的很困惑为什么在创建Firebase帐户时没有使用用户的电子邮件作为标识符。
  Future<FirebaseUser> signInWithApple() async {
    final AuthorizationResult result = await AppleSignIn.performRequests([
      AppleIdRequest(requestedScopes: [Scope.email, Scope.fullName])
    ]);

    switch (result.status) {
      case AuthorizationStatus.authorized:
        final AppleIdCredential appleIdCredential = result.credential;

        OAuthProvider oAuthProvider =
        new OAuthProvider(providerId: "apple.com");

        final AuthCredential credential = oAuthProvider.getCredential(
          idToken: String.fromCharCodes(appleIdCredential.identityToken),
          accessToken: String.fromCharCodes(
              appleIdCredential.authorizationCode),
        );

        await _firebaseAuth.signInWithCredential(credential);
        return _firebaseAuth.currentUser();

        break;

      case AuthorizationStatus.error:
        print('Sign in failed: ${result.error.localizedDescription}');
        break;

      case AuthorizationStatus.cancelled:
        print('User cancelled');
        break;
    }

    return null;
  }

enter image description here

5个回答

30

我认为这是按照预期工作的;

苹果只会在用户第一次登录设备并使用你的应用程序时返回完整的姓名和电子邮件,之后的任何登录都将返回这些信息的 null 值。我猜测你以前已经登录过,然后尝试通过新的 Firebase Auth 用户再次登录,但此时姓名/电子邮件不再可用。

为了测试目的,要再次接收这些信息,请转到您的设备设置; 设置> Apple ID、iCloud、iTunes 和 App Store > 密码与安全性 > 使用您的 Apple ID 的应用程序,点击你的应用程序并选择“停止使用 Apple ID”。现在您可以再次登录,然后您将再次接收完整的姓名和电子邮件。

这就是苹果设计他们的API的方式 - 因此建议您将这些信息存储在应用程序的其他地方,例如使用 shared_preferences 插件,以便在需要时始终可以访问它们。


是的,确实!这就是苹果的登录设计。刚意识到所有凭据只会被检索一次。 - stan
谢谢,我在这个问题上纠结了很长时间。现在明白为什么我没有收到电子邮件和姓名了。 - Md. Al-Amin
感谢您的出色回答!但是,重置Apple ID的应用程序使用情况对我来说并没有使电子邮件再次出现。是否有其他人遇到了同样的问题,还是这个问题只是模拟器的问题? - bd1909

5
问题在于iOS 13.6,而在13.5中我得到了姓名、电子邮件、令牌和标识符。但是在iOS 13.6中,只返回用户ID。我使用了sign_in_with_apple依赖项(https://pub.dev/packages/sign_in_with_apple)。

我在iOS 14上也遇到了同样的问题。你知道有没有解决方案吗? - Kitcc
请问您找到解决方案了吗? - Octet
同样的问题,有什么解决办法吗? - Abdullah Khan

1
以上的答案都很完美,但我想分享一些我在尝试了所有上述答案后仍然无法收到电子邮件的情况(甚至在登录时都没有问我是否想要分享电子邮件)。我在使用Flutter时遇到了这个问题,但对于IOS也可能适用。
  1. 如果你在开发中,进入设置 -> 密码与安全 -> 使用Apple ID登录 -> YOUR_APP_NAME -> 停止使用Apple ID

  2. Firebase控制台 -> 身份验证 -> 用户中删除名为“空白电子邮件”的用户。

  3. 添加作用域'email' (如果需要全名,则在作用域中添加'fullName'或其他所需内容),示例如下:

         final appleProvider = AppleAuthProvider();
         appleProvider.addScope('email');
         var credential = await FirebaseAuth.instance.signInWithProvider(appleProvider);
    
之后,弹出窗口会显示是否要分享电子邮件或隐藏以登录。处理IOS的情况,如果用户在弹出窗口中选择“隐藏”,则不分享电子邮件。

FirebaseAuth文档中没有提及范围。此外,添加电子邮件范围将使用户能够“隐藏我的电子邮件”。 - undefined

0
如果您要使用Firebase进行身份验证,请从Firebase用户中获取用户的电子邮件,只需这样做即可...
User? user = await FirebaseAuthOAuth().openSignInFlow("apple.com", ["email"], {"locale": "en"});

然后从用户获取数据,例如...

var email = user.email;

0

如果我们没有撤销该用户的访问令牌,那么通过AppleLogin返回的用户电子邮件、姓名和其他信息在第一次之后将为空。

你只需要撤销在第一次登录时生成的访问令牌,然后再尝试登录一次。

你可以使用以下请求来获取该访问令牌

 await post(
    'https://appleid.apple.com/auth/token',
    {
      'client_id': com/package.name,
      'client_secret': clientSecret,
      'code': authorizationCode,
      'grant_type': 'authorization_code',
      'redirect_uri': ''
    },

使用此请求来撤销访问令牌
 'https://appleid.apple.com/auth/revoke'
'client_id': com.package.name,
      'client_secret': clientSecret,
      'token':token

你需要使用私钥生成客户端密钥,你可以点击以下链接了解如何生成密钥。token: https://developer.apple.com/documentation/accountorganizationaldatasharing/creating-a-client-secret 这篇文章也很有帮助:通过Dart生成客户端密钥的Medium文章

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接