Flutter Web:Safari Google 登录首次尝试被阻止

6 safari dart firebase google-oauth flutter

我正在开发一个 Flutter Web 应用程序,该应用程序使用 Google Sign In 和 Firebase 身份验证。目前,Google 登录在大多数浏览器上运行完全正常。不过,我注意到,当在 iPhone 上使用 Safari 并阻止弹出窗口时,第一次身份验证失败,它不起作用(什么也没有出现)。看来,弹出窗口被阻止了。不过,通过立即点击按钮,身份验证就会成功。

Safari 中的第一次交互根本不起作用,尽管在 Firefox 或 Chrome 中可以。我还注意到 Google 登录方法在私人(隐身)浏览器中不起作用。

这是我当前的 googleSignIn() 方法:

static Future<void> signInWithGoogle() async {
try {
  final GoogleSignIn googleSignIn = GoogleSignIn();

  final GoogleSignInAccount? googleSignInAccount =
      await googleSignIn.signIn();

  if (googleSignInAccount != null) {
    final GoogleSignInAuthentication googleSignInAuthentication =
        await googleSignInAccount.authentication;

    final AuthCredential credential = GoogleAuthProvider.credential(
      accessToken: googleSignInAuthentication.accessToken,
      idToken: googleSignInAuthentication.idToken,
    );

    await FirebaseAuth.instance.signInWithCredential(credential);
  }
} catch (error) {
  throw error;
}
Run Code Online (Sandbox Code Playgroud)

}

如前所述,它在我测试过的所有其他浏览器中运行良好。当弹出窗口未被阻止时,它也可以在 Safari 中工作,尽管在第一次调用时它会询问用户是否允许弹出窗口。

我想指出的是,使用 Google Sign In 的其他网站不会遇到同样的问题,它似乎是 Flutter 的 Google Sign In 包特有的。

小智 4

在搜索 GitHub 和 StackOverflow 后,我找到了解决方案。在initState应用程序的初始屏幕中,调用GoogleSignIn().signInSilently()。这不是 Google 有意为之的功能,而是针对错误的一个令人愉快的解决方法。

有关更多背景信息,请参阅 Google 自己的google_sign_in 示例。一定要集中注意力initState

最后,如果您将 Firebase 身份验证与 Google Sign In 一起使用,则可以使用以下方法捕获silentSignIn()生成的用户对象,以便您获得好处。

static Future<void> signInWithGoogleSilently() async {
  try {
    final GoogleSignIn googleSignIn = GoogleSignIn();

    final GoogleSignInAccount? googleSignInAccount =
        await googleSignIn.signInSilently();

    if (googleSignInAccount != null) {
      final GoogleSignInAuthentication googleSignInAuthentication =
          await googleSignInAccount.authentication;

      final AuthCredential credential = GoogleAuthProvider.credential(
        accessToken: googleSignInAuthentication.accessToken,
        idToken: googleSignInAuthentication.idToken,
      );

      await FirebaseAuth.instance.signInWithCredential(credential);
    }
  } catch (error) {
    throw error;
  }
}
Run Code Online (Sandbox Code Playgroud)