handle401 static method
Handles 401 UnAuthorization errors by attempting to refresh the token or calling the logout callback.
Implementation
static Future<Result<String>> handle401(
Failure failure,
Future<Result<String>> Function() retryAction,
String endpoint,
) async {
// 1. Check if we are already on the refresh endpoint to avoid infinite loop
if (refreshTokenEndpoint != null && (endpoint == refreshTokenEndpoint || endpoint.endsWith(refreshTokenEndpoint!))) {
PackageLogger.error('401 on refresh endpoint - calling logout');
onLogout?.call();
return failure;
}
// 2. Check if current endpoint matches the whitelist (if provided)
// If list is empty/null: Trigger refresh for ALL 401 errors
bool isInWhitelist = refreshWhitelist == null || refreshWhitelist!.isEmpty || refreshWhitelist!.any((e) => endpoint == e || endpoint.endsWith(e));
// 3. If not in whitelist, directly call logout
if (!isInWhitelist) {
PackageLogger.warning('Endpoint not in whitelist - calling logout');
onLogout?.call();
return failure;
}
// 4. If refresh endpoint is not configured, call logout
if (refreshTokenEndpoint == null || refreshTokenEndpoint!.isEmpty) {
PackageLogger.error('No refresh endpoint configured - calling logout');
onLogout?.call();
return failure;
}
// 5. Attempt to refresh the token
try {
PackageLogger.log('Attempting to refresh token via $refreshTokenEndpoint');
// Get refresh token body from user callback or use empty body
final refreshBody = getRefreshTokenBody?.call() ?? {};
// Call the refresh token endpoint
final refreshResult = await post(
refreshTokenEndpoint!,
body: refreshBody,
isRetry: true, // Mark as retry to prevent infinite loop
);
// Check if refresh was successful
if (refreshResult is Success<String>) {
PackageLogger.success('Token refresh successful');
// Parse the response to extract new tokens
try {
final responseData = jsonDecode(refreshResult.value);
// Notify user to save the new tokens via callback
if (onTokenRefreshed != null) {
await onTokenRefreshed!(responseData is Map<String, dynamic> ? responseData : {'response': responseData});
}
// Retry the original request with new tokens
PackageLogger.log('Retrying original request after token refresh');
return await retryAction();
} catch (e) {
PackageLogger.error('Failed to parse refresh token response: $e');
onLogout?.call();
return failure;
}
} else {
// Refresh failed
PackageLogger.error('Token refresh failed - calling logout');
onLogout?.call();
return failure;
}
} catch (e) {
PackageLogger.error('Error during token refresh: $e');
onLogout?.call();
return failure;
}
}