From 04896349d6c4eb3ae2cb0a8c81cd85b00b6ff961 Mon Sep 17 00:00:00 2001 From: dahoud <41957584+DahoudG@users.noreply.github.com> Date: Fri, 10 Apr 2026 20:53:28 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20BUG-02=20IC-03=20session=20expir=C3=A9e?= =?UTF-8?q?=20sur=20Workflow=20Financier=20et=20Messagerie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajoute KeycloakAuthService.getValidAccessToken() qui vérifie l'expiration du JWT et rafraîchit automatiquement avant de retourner le token. FinanceWorkflowRemoteDatasource et MessagingRemoteDatasource injectent désormais KeycloakAuthService au lieu de FlutterSecureStorage directement, ce qui évite d'envoyer un Bearer expiré et d'obtenir un 401 silencieux. --- .../data/datasources/keycloak_auth_service.dart | 11 +++++++++++ .../data/datasources/messaging_remote_datasource.dart | 10 +++++----- .../finance_workflow_remote_datasource.dart | 10 +++++----- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/features/authentication/data/datasources/keycloak_auth_service.dart b/lib/features/authentication/data/datasources/keycloak_auth_service.dart index f8e5899..f0626cc 100644 --- a/lib/features/authentication/data/datasources/keycloak_auth_service.dart +++ b/lib/features/authentication/data/datasources/keycloak_auth_service.dart @@ -119,6 +119,17 @@ class KeycloakAuthService { return null; } + /// Retourne un access token valide, en rafraîchissant automatiquement si expiré. + /// Utilisé par les datasources pour éviter d'envoyer un Bearer null ou expiré. + Future getValidAccessToken() async { + String? token = await _storage.read(key: _accessK); + if (token == null) return null; + if (JwtDecoder.isExpired(token)) { + token = await refreshToken(); + } + return token; + } + /// Récupération de l'utilisateur courant + Mapage Rôles Future getCurrentUser() async { String? token = await _storage.read(key: _accessK); diff --git a/lib/features/communication/data/datasources/messaging_remote_datasource.dart b/lib/features/communication/data/datasources/messaging_remote_datasource.dart index 2895e9c..fe1ecb2 100644 --- a/lib/features/communication/data/datasources/messaging_remote_datasource.dart +++ b/lib/features/communication/data/datasources/messaging_remote_datasource.dart @@ -4,10 +4,10 @@ library messaging_remote_datasource; import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:injectable/injectable.dart'; import '../../../../core/config/environment.dart'; import '../../../../core/error/exceptions.dart'; +import '../../../authentication/data/datasources/keycloak_auth_service.dart'; import '../models/message_model.dart'; import '../models/conversation_model.dart'; import '../../domain/entities/message.dart'; @@ -15,16 +15,16 @@ import '../../domain/entities/message.dart'; @lazySingleton class MessagingRemoteDatasource { final http.Client client; - final FlutterSecureStorage secureStorage; + final KeycloakAuthService authService; MessagingRemoteDatasource({ required this.client, - required this.secureStorage, + required this.authService, }); - /// Headers HTTP avec authentification + /// Headers HTTP avec authentification — rafraîchit le token si expiré (fix IC-03) Future> _getHeaders() async { - final token = await secureStorage.read(key: 'kc_access'); + final token = await authService.getValidAccessToken(); return { 'Content-Type': 'application/json', 'Accept': 'application/json', diff --git a/lib/features/finance_workflow/data/datasources/finance_workflow_remote_datasource.dart b/lib/features/finance_workflow/data/datasources/finance_workflow_remote_datasource.dart index e93538f..4bb0ed6 100644 --- a/lib/features/finance_workflow/data/datasources/finance_workflow_remote_datasource.dart +++ b/lib/features/finance_workflow/data/datasources/finance_workflow_remote_datasource.dart @@ -3,26 +3,26 @@ library finance_workflow_remote_datasource; import 'dart:convert'; import 'package:http/http.dart' as http; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:injectable/injectable.dart'; import '../../../../core/config/environment.dart'; import '../../../../core/error/exceptions.dart'; +import '../../../authentication/data/datasources/keycloak_auth_service.dart'; import '../models/transaction_approval_model.dart'; import '../models/budget_model.dart'; @lazySingleton class FinanceWorkflowRemoteDatasource { final http.Client client; - final FlutterSecureStorage secureStorage; + final KeycloakAuthService authService; FinanceWorkflowRemoteDatasource({ required this.client, - required this.secureStorage, + required this.authService, }); - /// Headers HTTP avec authentification + /// Headers HTTP avec authentification — rafraîchit le token si expiré (fix IC-03) Future> _getHeaders() async { - final token = await secureStorage.read(key: 'kc_access'); + final token = await authService.getValidAccessToken(); return { 'Content-Type': 'application/json', 'Accept': 'application/json',