颤动网页Google_Sign_in:如何检索刷新令牌 [英] Flutter web google_sign_in: How to retrieve refreshToken

查看:14
本文介绍了颤动网页Google_Sign_in:如何检索刷新令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

google_sign_in不返回refreshToken。有没有办法登录Google并接收刷新令牌,该令牌可以发送到API以进一步访问用户数据?

也可以使用serverAuthCode获取刷新令牌,该代码目前始终为空。已创建多个问题来描述此问题:

是否有方法可以使用Google登录进行身份验证并接收刷新令牌或serverAuthCode?

推荐答案

Google Sign In基于OAuth2,用户可以创建自己的流程实现。

以下是Google Sign In服务的代码片段,可用于检索刷新令牌:

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();

这篇关于颤动网页Google_Sign_in:如何检索刷新令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆