Flutter:当令牌与渡轮(graphql)客户端过期时如何刷新令牌?

Flutter: How to refresh token when token expires with ferry (graphql) client?

如何在 ferry (graphql) 客户端中使用刷新令牌检索新令牌?

突变后的响应如下所示:

{
  "data": {
    "auth_login": {
      "access_token": "ey...",
      "refresh_token": "Ua...",
      "expires": 900000
    }
  }
}

我试图用 fresh_graphql 完成它,但它不起作用。 authenticationStatus 始终未通过身份验证,但令牌始终合法。

实施:

import 'dart:math';

import 'package:ferry/ferry.dart';
import 'package:ferry_hive_store/ferry_hive_store.dart';
import 'package:fresh_graphql/fresh_graphql.dart';
import 'package:gql_http_link/gql_http_link.dart';
import 'package:hive/hive.dart';

Future<Client> initClient(String? accessToken, String? refreshToken) async {
  Hive.init('hive_data');

  final box = await Hive.openBox<Map<String, dynamic>>('graphql');

  await box.clear();

  final store = HiveStore(box);

  final cache = Cache(store: store);

  final freshLink = await setFreshLink(accessToken ?? '', refreshToken);

  final link = Link.from(
      [freshLink, HttpLink('https://.../graphql/')]);

  final client = Client(
    link: link,
    cache: cache,
  );

  return client;
}

Future<FreshLink> setFreshLink(String accessToken, String? refreshToken) async {
  final freshLink = FreshLink<dynamic>(
    tokenStorage: InMemoryTokenStorage<dynamic>(),
    refreshToken: (dynamic token, client) async {
      print('refreshing token!');
      await Future<void>.delayed(const Duration(seconds: 1));
      if (Random().nextInt(1) == 0) {
        throw RevokeTokenException();
      }
      return OAuth2Token(
        accessToken: 'top_secret_refreshed',
      );
    },
    shouldRefresh: (_) => Random().nextInt(2) == 0,
  )..authenticationStatus.listen(print);

  print(freshLink.token);
  print(freshLink.authenticationStatus);

  await freshLink
      .setToken(OAuth2Token(tokenType: 'Bearer', accessToken: accessToken));

  return freshLink;
}

任何解决方案,即使没有 fresh_graphql,我们将不胜感激!

我初始化轮渡客户端的方式如下。

  1. 创建一个继承自 AuthLink 的 CustomAuthLink。

    import 'package:gql_http_link/gql_http_link.dart';
    
    class _CustomAuthLink extends AuthLink {
       _CustomAuthLink() : super(
          getToken: () {
            // ...
            // Call your api to refresh the token and return it
            // ...
            String token = await ... // api refresh call
            return "Bearer $token"
          }
       );
    }
    
  2. 使用此自定义身份验证 link 初始化您的客户端。

    ...
    final link = Link.from([freshLink, HttpLink('https://.../graphql/')]); 
    ...
    Client(
      link: _CustomAuthLink().concat(link),
    )
    ...
    
  3. 我不确定您是否还需要 freshLink。您可能想删除它并将 HttpLink(...) 直接传递给 .concat(...) 方法。