[英]Flutter web google_sign_in: How to retrieve refreshToken
google_sign_in不返回refreshToken
。 有沒有辦法通過 Google 登錄並接收刷新令牌,該令牌可以發送到 API 以進一步訪問用戶數據?
刷新令牌也可以使用 serverAuthCode 獲得,此時它始終為空。 已經創建了多個問題來描述這個問題:
有沒有辦法通過 Google Sign In 進行身份驗證並接收 refreshToken 或 serverAuthCode?
Google Sign In 基於 oAuth2,您可以創建自己的流程實現。
這是可用於檢索 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 'GoogleSignInUser{accessToken: $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();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.