Search code examples
apiflutterdartflutter-dependencieschopper

Flutter Chopper 401 renew & retry interceptor


I'm using Chopper in my flutter app and what I need to do is, when I get 401 response status code (unauthorized) from my API, I must call another endpoint that will refresh my token and save it into secured storage, when all of this is done, I need to retry the request instantly (so that user cannot notice that his token expired). Is this dooable with Chopper only, or I have to use some other package?


Solution

  • It is possible. You need to use the authenticator field on the Chopper client, e.g.

     final ChopperClient client = ChopperClient(
      baseUrl: backendUrl,
      interceptors: [HeaderInterceptor()],
      services: <ChopperService>[
        _$UserApiService(),
      ],
      converter: converter,
      authenticator: MyAuthenticator(),
    );
    

    And your authenticator class, should look something like this:

    class MyAuthenticator extends Authenticator {
      @override
      FutureOr<Request?> authenticate(
       Request request, Response<dynamic> response) async {
       if (response.statusCode == 401) {
         String? newToken = await refreshToken();
    
          final Map<String, String> updatedHeaders =
             Map<String, String>.of(request.headers);
    
            if (newToken != null) {
              newToken = 'Bearer $newToken';
              updatedHeaders.update('Authorization', (String _) => newToken!,
               ifAbsent: () => newToken!);
             return request.copyWith(headers: updatedHeaders);
            }
          }
        return null;
     }
    

    Admittedly, it wasn't that easy to find/understand (though it is the first property of the chopper client mentioned in their docs), but it is precisely what this property is for. I was going to move to dio myself, but I still had the same issue with type conversion on a retry.

    EDIT: You will probably want to keep a retry count somewhere so you don't end up in a loop.