fix: BUG-02 IC-03 session expirée sur Workflow Financier et Messagerie
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.
This commit is contained in:
@@ -119,6 +119,17 @@ class KeycloakAuthService {
|
|||||||
return null;
|
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<String?> 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
|
/// Récupération de l'utilisateur courant + Mapage Rôles
|
||||||
Future<User?> getCurrentUser() async {
|
Future<User?> getCurrentUser() async {
|
||||||
String? token = await _storage.read(key: _accessK);
|
String? token = await _storage.read(key: _accessK);
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ library messaging_remote_datasource;
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
import '../../../../core/config/environment.dart';
|
import '../../../../core/config/environment.dart';
|
||||||
import '../../../../core/error/exceptions.dart';
|
import '../../../../core/error/exceptions.dart';
|
||||||
|
import '../../../authentication/data/datasources/keycloak_auth_service.dart';
|
||||||
import '../models/message_model.dart';
|
import '../models/message_model.dart';
|
||||||
import '../models/conversation_model.dart';
|
import '../models/conversation_model.dart';
|
||||||
import '../../domain/entities/message.dart';
|
import '../../domain/entities/message.dart';
|
||||||
@@ -15,16 +15,16 @@ import '../../domain/entities/message.dart';
|
|||||||
@lazySingleton
|
@lazySingleton
|
||||||
class MessagingRemoteDatasource {
|
class MessagingRemoteDatasource {
|
||||||
final http.Client client;
|
final http.Client client;
|
||||||
final FlutterSecureStorage secureStorage;
|
final KeycloakAuthService authService;
|
||||||
|
|
||||||
MessagingRemoteDatasource({
|
MessagingRemoteDatasource({
|
||||||
required this.client,
|
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<Map<String, String>> _getHeaders() async {
|
Future<Map<String, String>> _getHeaders() async {
|
||||||
final token = await secureStorage.read(key: 'kc_access');
|
final token = await authService.getValidAccessToken();
|
||||||
return {
|
return {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
|
|||||||
@@ -3,26 +3,26 @@ library finance_workflow_remote_datasource;
|
|||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
import '../../../../core/config/environment.dart';
|
import '../../../../core/config/environment.dart';
|
||||||
import '../../../../core/error/exceptions.dart';
|
import '../../../../core/error/exceptions.dart';
|
||||||
|
import '../../../authentication/data/datasources/keycloak_auth_service.dart';
|
||||||
import '../models/transaction_approval_model.dart';
|
import '../models/transaction_approval_model.dart';
|
||||||
import '../models/budget_model.dart';
|
import '../models/budget_model.dart';
|
||||||
|
|
||||||
@lazySingleton
|
@lazySingleton
|
||||||
class FinanceWorkflowRemoteDatasource {
|
class FinanceWorkflowRemoteDatasource {
|
||||||
final http.Client client;
|
final http.Client client;
|
||||||
final FlutterSecureStorage secureStorage;
|
final KeycloakAuthService authService;
|
||||||
|
|
||||||
FinanceWorkflowRemoteDatasource({
|
FinanceWorkflowRemoteDatasource({
|
||||||
required this.client,
|
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<Map<String, String>> _getHeaders() async {
|
Future<Map<String, String>> _getHeaders() async {
|
||||||
final token = await secureStorage.read(key: 'kc_access');
|
final token = await authService.getValidAccessToken();
|
||||||
return {
|
return {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
|
|||||||
Reference in New Issue
Block a user