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

Google Sign In中serverAuthCode返回null问题求助

解决Google登录serverAuthCode返回null的问题

问题重现

应用日志

D/EGL_emulation( 9260): app_time_stats: avg=83219.91ms min=1.44ms max=2329685.50ms count=28
W/Auth    ( 9260): [GoogleAuthUtil] isUserRecoverableError status: NEED_REMOTE_CONSENT
I/flutter ( 9260): Google Access Token: ya29.a0AfB_byBhIKqNK1teL9pzZNxgktKDnX2KhStaxB8X1pmxS0EPGphifjZdmXFHMW5R5-j70PRE-2sYmPIr1EttYQTBsibG89ZGzjOq2b_Nal3G5n3P3QpFI2YAERNnsozvh1Vh0A-BuPuQDAnGeRzY4FFzrzs-gAgeJAaCgYKASMSARASFQHGX2MibSgPlsx9vVc3vLiAkYNKsQ0169
I/flutter ( 9260): Google Server Auth Code:
I/flutter ( 9260): Google Id Token:
I/flutter ( 9260): Google Email: nurain.cubosquare@gmail.com
I/flutter ( 9260): Google Id : 113699528046273182780

实现代码

// Add these imports at the top of your file
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';

class GoogleSignInApi {
  static final _googleSignIn = GoogleSignIn(scopes: [
    'email',
    'https://www.googleapis.com/auth/userinfo.profile',
  ]);

  static Future<GoogleSignInAccount?> signIn() => _googleSignIn.signIn();
}

class YourWidget extends StatefulWidget {
  @override
  _YourWidgetState createState() => _YourWidgetState();
}

class _YourWidgetState extends State<YourWidget> {
  String googleEmail = '';
  String googleId = '';
  String googlePhotoUrl = '';
  String googleServerAuthCode = '';
  String googleAccessToken = '';
  String googleIdToken = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            _handleSignIn();
          },
          child: Text('Sign In with Google'),
        ),
      ),
    );
  }

  void _handleSignIn() {
    GoogleSignInApi.signIn().then((userData) {
      if (userData != null) {
        userData.authentication.then((googleKey) {
          setState(() {
            // Retrieve the data from Google auth
            googleEmail = userData.email;
            googleId = userData.id;
            // googlePhotoUrl = userData.photoUrl;
            googleServerAuthCode = userData.serverAuthCode ?? '';
            googleAccessToken = googleKey.accessToken ?? '';
            googleIdToken = googleKey.idToken ?? '';
          });
          print("Google Access Token: $googleAccessToken");
          print("Google Server Auth Code: $googleServerAuthCode");
          print("Google Id Token: $googleIdToken");
          print("Google Email: $googleEmail");
          print("Google Id : $googleId");
          // Call your login function if no errors
          checkInternetAndLoginWithGoogle();
        }).catchError((err) {
          print('Inner error: $err');
        });
      } else {
        print('User cancelled sign in');
      }
    }).catchError((err) {
      print('Error occurred: $err');
    });
  }

  void checkInternetAndLoginWithGoogle() {
    // Implement your login logic here
    // This method will be called after successfully retrieving Google user data
  }
}

解决方法

1. 配置Web客户端ID(核心步骤)

serverAuthCode仅在初始化GoogleSignIn时指定Web类型客户端ID后才会返回,这是当前代码的核心缺失项:

  • 登录Google Cloud控制台,找到你的OAuth 2.0客户端ID,选择Web应用类型的ID(不要用Android/iOS客户端ID)。
  • 修改GoogleSignInApi初始化代码:
class GoogleSignInApi {
  static final _googleSignIn = GoogleSignIn(
    scopes: [
      'email',
      'https://www.googleapis.com/auth/userinfo.profile',
    ],
    // 替换为你的Web客户端ID
    clientId: 'YOUR_WEB_CLIENT_ID.apps.googleusercontent.com',
  );

  static Future<GoogleSignInAccount?> signIn() => _googleSignIn.signIn();
}

2. 处理NEED_REMOTE_CONSENT警告

该警告表示用户需要重新授权,可通过「先静默登录、失败再触发显式授权」的流程优化:

void _handleSignIn() {
  GoogleSignInApi._googleSignIn.signInSilently().then((userData) {
    if (userData != null) {
      _fetchAuthData(userData);
    } else {
      GoogleSignInApi.signIn().then((userData) {
        if (userData != null) {
          _fetchAuthData(userData);
        } else {
          print('User cancelled sign in');
        }
      }).catchError((err) {
        print('Error occurred: $err');
      });
    }
  }).catchError((err) {
    print('Silent sign in failed: $err');
    GoogleSignInApi.signIn().then((userData) {
      if (userData != null) {
        _fetchAuthData(userData);
      }
    });
  });
}

// 提取授权数据获取逻辑到单独方法
void _fetchAuthData(GoogleSignInAccount userData) {
  userData.authentication.then((googleKey) {
    setState(() {
      googleEmail = userData.email;
      googleId = userData.id;
      googleServerAuthCode = userData.serverAuthCode ?? '';
      googleAccessToken = googleKey.accessToken ?? '';
      googleIdToken = googleKey.idToken ?? '';
    });
    print("Google Access Token: $googleAccessToken");
    print("Google Server Auth Code: $googleServerAuthCode");
    print("Google Id Token: $googleIdToken");
    print("Google Email: $googleEmail");
    print("Google Id : $googleId");
    checkInternetAndLoginWithGoogle();
  }).catchError((err) {
    print('Inner error: $err');
  });
}

3. 验证OAuth同意屏幕配置

  • 确保Google Cloud控制台的OAuth同意屏幕已发布(针对外部用户),添加的权限范围已完成审核。
  • 测试时使用已添加到测试用户列表的账号,避免权限未发布导致的授权异常。

内容的提问来源于stack exchange,提问作者Raza Mehdi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:00:14