google-sign-in-web分离认证授权后,如何获取firebase_auth所需access_token?
解决google-sign-in-web无法获取accessToken的问题
原因说明
google-sign-in-web将认证(Authentication)与授权(Authorization)分离后,仅请求OpenID相关的scope(如profile、email、openid)时,GoogleSignInAuthentication对象不会返回accessToken——这类scope仅用于身份认证,而accessToken是授权凭证,需要请求至少一个授权类scope才能触发返回。
方案一:添加授权类scope(推荐)
修改你的scope列表,加入至少一个需要授权的scope(比如用户信息相关的https://www.googleapis.com/auth/userinfo.profile),重新执行登录流程即可获取accessToken:
import 'package:firebase_auth/firebase_auth.dart' as auth; import 'package:google_sign_in/google_sign_in.dart'; // 修改scope列表,添加授权类scope const List<String> scopes = <String>[ 'profile', 'email', 'openid', 'https://www.googleapis.com/auth/userinfo.profile', ]; // 原有登录流程不变 final GoogleSignIn _googleSignIn = GoogleSignIn(scopes: scopes); GoogleSignInAccount? googleUser = await _googleSignIn.signInSilently(); final GoogleSignInAuthentication googleAuth = await googleUser.authentication; debugPrint('googleAuth.accessToken: ${googleAuth.accessToken}'); // 现在应该能获取到值 debugPrint('googleAuth.idToken: ${googleAuth.idToken}'); final auth.AuthCredential credential = auth.GoogleAuthProvider.credential( accessToken: googleAuth.accessToken, idToken: googleAuth.idToken, ); final auth.UserCredential userCredential = await _auth.signInWithCredential(credential);
方案二:通过JS互操作直接获取(适用于无法添加额外scope的场景)
如果控制台已显示accessToken但无法通过原有流程获取,可以通过Dart的JS互操作直接读取浏览器中的授权凭证:
- 先在
pubspec.yaml中添加js依赖:
dependencies: js: ^0.6.7
- 在代码中实现获取方法:
import 'dart:js' as js; import 'package:google_sign_in/google_sign_in.dart'; import 'package:flutter/foundation.dart'; // 在登录完成后调用此方法获取accessToken Future<String?> fetchAccessToken() async { try { final tokenResponse = await js.promiseToFuture( js.context['google']?['accounts']?['oauth2']?['getToken']?.call( js.JsObject.jsify({'scope': 'profile email openid'}), ), ); return tokenResponse?['access_token']; } catch (e) { debugPrint('获取accessToken失败: $e'); return null; } } // 使用示例 GoogleSignInAccount? googleUser = await _googleSignIn.signInSilently(); if (googleUser != null) { String? accessToken = await fetchAccessToken(); debugPrint('获取到的accessToken: $accessToken'); }
内容的提问来源于stack exchange,提问作者Simpler
相关产品推荐
相关产品推荐

