withOAuth401Retry<T> function

Future<T> withOAuth401Retry<T>({
  1. required Future<T> request(),
  2. required Future<void> handleOAuth401Error(
    1. String failedAccessToken
    ),
  3. required String? getAccessToken(),
  4. bool also403Revoked = false,
})

Wrapper that handles OAuth 401 errors by retrying once.

The request closure is called again on retry, so it should re-read auth to pick up the refreshed token.

Implementation

Future<T> withOAuth401Retry<T>({
  required Future<T> Function() request,
  required Future<void> Function(String failedAccessToken) handleOAuth401Error,
  required String? Function() getAccessToken,
  bool also403Revoked = false,
}) async {
  try {
    return await request();
  } on HttpException catch (e) {
    final statusCode = _extractStatusCode(e);
    final isAuthError =
        statusCode == 401 ||
        (also403Revoked &&
            statusCode == 403 &&
            e.message.contains('OAuth token has been revoked'));

    if (!isAuthError) rethrow;

    final failedAccessToken = getAccessToken();
    if (failedAccessToken == null) rethrow;

    await handleOAuth401Error(failedAccessToken);
    return await request();
  }
}