简体   繁体   中英

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

How to retrieve a new token with a refresh token in flutter in a ferry (graphql) client?

The response after a mutation looks like this:

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

I tried to accomplish it with fresh_graphql, but it does not work. The authenticationStatus is always unauthenticated but the token was always legit.

Implementation:

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;
}

Any solution, even without fresh_graphql, would be appreciated!

The way I initialize my ferry client is as follows.

  1. Create a CustomAuthLink that inherits from AuthLink.

     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. Use this custom auth link to initialise your client.

     ... final link = Link.from([freshLink, HttpLink('https://.../graphql/')]); ... Client( link: _CustomAuthLink().concat(link), )...
  3. I am not sure if you still going to need freshLink anymore. You might wanna remove it and pass HttpLink(...) directly into the .concat(...) method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM