Harden AuthInterceptor: retry guard, single-flight refresh, shared pref keys

Addresses PR review on the auth interceptor:

- Guard against unbounded retry recursion: tag the replayed request with
  extra['auth_retried'] and skip the refresh/replay path on a second 401 so
  it can't recurse refresh -> replay indefinitely. Drop the redundant manual
  Authorization header on the replay (onRequest re-injects it).
- Fix the concurrent-refresh race: coalesce concurrent 401s onto a single
  in-flight refresh future so the rotating refresh token is only consumed
  once, instead of later refreshes posting an already-consumed token and
  spuriously logging out. (Chose the shared-future approach over
  QueuedInterceptor, which deadlocks with the replay-via-same-Dio pattern.)
- Centralise the 'bearer' / 'refresh_token' / 'customer_data' pref keys in
  a PrefKeys constants class used by the interceptor, network manager, auth
  service and router so they can't silently diverge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
AmirReza Jamali
2026-06-10 12:21:03 +03:30
parent 633f0ba881
commit deda384aaa
5 changed files with 76 additions and 22 deletions
+2 -1
View File
@@ -18,6 +18,7 @@ import '../../views/profile/pages/profile_screen.dart';
import '../../views/splash/pages/splash_screen.dart';
import '../../views/tenders/pages/tenders_screen.dart';
import '../../views/your_tenders/pages/your_tenders_screen.dart';
import '../constants/pref_keys.dart';
import '../providers/board_provider.dart';
import '../providers/final_completion_provider.dart';
import '../providers/forgot_password_provider.dart';
@@ -51,7 +52,7 @@ final GoRouter appRouter = GoRouter(
navigatorKey: rootNavigatorKey,
redirect: (context, state) {
final prefs = context.read<SharedPreferences>();
final hasToken = prefs.getString('bearer') != null;
final hasToken = prefs.getString(PrefKeys.bearer) != null;
final path = state.uri.path;
final location = state.matchedLocation;
final isSplash = path == '/splash' || location == '/splash';