You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修改Firebase用户账户关联选项后Google登录无法获取用户邮箱

问题描述

我修改了Firebase Authentication的用户账户关联设置,选择了“为每个身份提供商创建多个账户”选项。现在用户通过Google登录时,无法获取user.email字段,但user.displayName、user.photoURL等其他用户信息都能正常获取。以下是我的实现代码:

void signUpWithGoogle(context) async {
  try {

    showDialog(
      context: context,
      builder: (context) => Container(
        color: Colors.black,
        child: const Center(
          child: CircularProgressIndicator(
            color: Colors.white,
          ),
        ),
      ),
    );
    final GoogleSignInAccount? googleSignInAccount = await googleSignIn.signIn();
    final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount!.authentication;

    // provider.setCustomParameters({});
    final AuthCredential authCredential = GoogleAuthProvider.credential(
        idToken: googleSignInAuthentication.idToken,
        accessToken: googleSignInAuthentication.accessToken);

    UserCredential result = await fireAuth.signInWithCredential(authCredential);
    globals.user = result.user;

    if(!await UserData().isUserExists(FirebaseAuth.instance.currentUser!.uid)) {
      debugPrint("_-_-_-_-_-_ NEW USER _-_-_-_-_-_\n ${result.user} \n ${globals.user.email}\n ${globals.user.displayName}\n ${globals.user.photoURL}");
      UserData(true, globals.user.email, globals.user.displayName, globals.user.photoURL).addUser(FirebaseAuth.instance.currentUser!.uid);
    } else {
      debugPrint("_-_-_-_-_-_ USER ALREADY EXISTS _-_-_-_-_-_");
    }

    if(result != null) {
      Navigator.of(context).pushAndRemoveUntil(
        // MaterialPageRoute(builder: (context) => const HomeScreen()),(Route<dynamic> route) => false
        PageRouteBuilder(
            pageBuilder: (_, __, ___) => const HomeScreen(),
            transitionDuration: const Duration(milliseconds: 1500),
            transitionsBuilder: (_, a, __, c) => FadeTransition(
              opacity: a,
              child: c,
            )), (Route<dynamic> route) => false
      );
    } else {
      debugPrint(" RESULT USER IS NULL =>=>=> ");
    }
  } catch (exception) {
    if(exception is PlatformException) {
      if(exception.code == GoogleSignIn.kNetworkError) {
        showAlert(context, "You have Poor Connectivity.");
      } else {
        debugPrint("YOU HAVE EXCEPTION IN GOOGLE SIGN IN ${exception.code}");
      }
    }
    debugPrint("YOU HAVE PROBLEM IN GOOGLE SIGN IN $exception");
  }
}
解决方案

原因分析

选择“为每个身份提供商创建多个账户”后,Firebase不会自动合并不同提供商的权限请求。Google登录时,邮箱属于需要明确请求的权限字段,而displayName、photoURL是默认公开的基础信息,所以会被正常返回。

解决步骤

  1. 添加Google登录的邮箱权限
    初始化GoogleSignIn时,指定scopes参数明确请求邮箱权限:

    final GoogleSignIn googleSignIn = GoogleSignIn(
      scopes: [
        'email',
        'profile', // 可选,确保获取基础用户信息
      ],
    );
    
  2. 从GoogleSignInAccount直接提取邮箱
    即使Firebase User对象的email为空,也可以直接从GoogleSignInAccount中获取邮箱,再同步到全局变量或Firebase用户信息:

    final GoogleSignInAccount? googleSignInAccount = await googleSignIn.signIn();
    if (googleSignInAccount != null) {
      String? userEmail = googleSignInAccount.email;
      // 若Firebase User的email为空,手动补全
      if (globals.user?.email == null && userEmail != null) {
        globals.user = globals.user?.copyWith(email: userEmail);
      }
    }
    
  3. 确认Firebase控制台设置
    进入Firebase控制台 → Authentication → 登录方法 → Google,检查“获取用户的电子邮件地址”选项是否已启用(默认开启,建议确认)。

修改后的代码示例

// 初始化GoogleSignIn时添加权限
final GoogleSignIn googleSignIn = GoogleSignIn(
  scopes: ['email', 'profile'],
);

void signUpWithGoogle(context) async {
  try {
    showDialog(
      context: context,
      builder: (context) => Container(
        color: Colors.black,
        child: const Center(
          child: CircularProgressIndicator(color: Colors.white),
        ),
      ),
    );

    final GoogleSignInAccount? googleSignInAccount = await googleSignIn.signIn();
    if (googleSignInAccount == null) {
      Navigator.of(context).pop();
      return;
    }
    final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;

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

    UserCredential result = await fireAuth.signInWithCredential(authCredential);
    globals.user = result.user;

    // 从Google账户获取邮箱并补全
    String? userEmail = googleSignInAccount.email;
    if (globals.user?.email == null && userEmail != null) {
      globals.user = globals.user?.copyWith(email: userEmail);
    }

    if(!await UserData().isUserExists(FirebaseAuth.instance.currentUser!.uid)) {
      debugPrint("_-_-_-_-_-_ NEW USER _-_-_-_-_-_\n ${result.user} \n ${globals.user?.email}\n ${globals.user?.displayName}\n ${globals.user?.photoURL}");
      UserData(true, globals.user?.email, globals.user?.displayName, globals.user?.photoURL).addUser(FirebaseAuth.instance.currentUser!.uid);
    } else {
      debugPrint("_-_-_-_-_-_ USER ALREADY EXISTS _-_-_-_-_-_");
    }

    Navigator.of(context).pushAndRemoveUntil(
      PageRouteBuilder(
          pageBuilder: (_, __, ___) => const HomeScreen(),
          transitionDuration: const Duration(milliseconds: 1500),
          transitionsBuilder: (_, a, __, c) => FadeTransition(opacity: a, child: c)),
      (Route<dynamic> route) => false
    );
  } catch (exception) {
    if(exception is PlatformException) {
      if(exception.code == GoogleSignIn.kNetworkError) {
        showAlert(context, "网络连接不佳。");
      } else {
        debugPrint("Google登录异常:${exception.code}");
      }
    }
    debugPrint("Google登录出错:$exception");
  }
}

内容的提问来源于stack exchange,提问作者Dhanrajsinh Parmar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 09:52:03