Flutter web google_sign_in:如何检索refreshToken
Posted
技术标签:
【中文标题】Flutter web google_sign_in:如何检索refreshToken【英文标题】:Flutter web google_sign_in: How to retrieve refreshToken 【发布时间】:2021-12-13 04:19:46 【问题描述】:google_sign_in 不返回 refreshToken
。有没有办法通过 Google 登录并接收可以发送到 API 以进一步访问用户数据的刷新令牌?
刷新令牌也可以通过 serverAuthCode 获得,此时它始终为空。已经创建了多个问题来描述此问题:
https://github.com/flutter/flutter/issues/45847 https://github.com/flutter/flutter/issues/57712 https://github.com/flutter/flutter/issues/15796 https://github.com/flutter/flutter/issues/62474有没有办法通过 Google Sign In 进行身份验证并接收 refreshToken 或 serverAuthCode?p>
【问题讨论】:
【参考方案1】:Google 登录基于 oAuth2,可以创建自己的流程实现。
这是一个 google 登录服务的代码 sn-p,可用于检索 refreshToken:
import 'dart:async';
import 'dart:html' as html;
import 'package:oauth2/oauth2.dart' as oauth2;
class GoogleSignInService
final authorizationEndpoint =
Uri.parse('https://accounts.google.com/o/oauth2/v2/auth');
final tokenEndpoint = Uri.parse('https://oauth2.googleapis.com/token');
final String identifier;
final String secret;
final String baseUrl;
final List<String> scopes;
_SignInSession? _signInSession;
Uri get redirectUrl => Uri.parse('$baseUrl/callback.html');
GoogleSignInService(
required this.identifier,
required this.secret,
required this.baseUrl,
required this.scopes,
)
html.window.addEventListener('message', _eventListener);
void _eventListener(html.Event event)
_signInSession?.completeWithCode((event as html.MessageEvent).data);
Future<GoogleSignInUser?> signIn() async
if (_signInSession != null)
return null;
final grant = oauth2.AuthorizationCodeGrant(
identifier,
authorizationEndpoint,
tokenEndpoint,
secret: secret,
);
var authorizationUrl = grant.getAuthorizationUrl(
redirectUrl,
scopes: scopes,
);
final url =
'$authorizationUrl.toString()&access_type=offline&prompt=select_account+consent';
_signInSession = _SignInSession(url);
final code = await _signInSession!.codeCompleter.future;
if (code != null)
final client = await grant.handleAuthorizationResponse('code': code);
return GoogleSignInUser(
accessToken: client.credentials.accessToken,
refreshToken: client.credentials.refreshToken,
idToken: client.credentials.idToken!,
);
else
return null;
class GoogleSignInUser
final String accessToken;
final String? refreshToken;
final String idToken;
const GoogleSignInUser(
required this.accessToken,
required this.refreshToken,
required this.idToken,
);
@override
String toString()
return 'GoogleSignInUseraccessToken: $accessToken, refreshToken: $refreshToken, idToken: $idToken';
class _SignInSession
final codeCompleter = Completer<String?>();
late final html.WindowBase _window;
late final Timer _timer;
bool get isClosed => codeCompleter.isCompleted;
_SignInSession(String url)
_window =
html.window.open(url, '_blank', 'location=yes,width=550,height=600');
_timer = Timer.periodic(const Duration(milliseconds: 500), (timer)
if (_window.closed == true)
if (!isClosed)
codeCompleter.complete(null);
_timer.cancel();
);
void completeWithCode(String code)
if (!isClosed)
codeCompleter.complete(code);
确保同时创建web/callback.html
文件:
<html>
<body>
</body>
<script>
function findGetParameter(parameterName)
var result = null,
tmp = [];
location.search
.substr(1)
.split("&")
.forEach(function (item)
tmp = item.split("=");
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
);
return result;
let code = findGetParameter('code');
window.opener.postMessage(code, "http://localhost:5000");
window.close();
</script>
</html>
将http://localhost:5000
更改为您在生产中使用的任何域。
示例用法:
final googleSignIn = GoogleSignInService(
identifier: 'CLIENT_ID',
secret: 'CLIENT_SECRET',
baseUrl: 'http://localhost:5000',
scopes: [
'email',
],
),
final user = await googleSignIn.signIn();
【讨论】:
是你的main.dart的最高代码sn-p吗?没看到主线或者,您如何在 main.dart 中调用它? 有一个示例使用代码 sn-p。随心所欲地使用它。例如,在用户点击“登录”按钮后 好的,我会弄清楚如何构建我的 main.dart 以进行测试。以上是关于Flutter web google_sign_in:如何检索refreshToken的主要内容,如果未能解决你的问题,请参考以下文章