feat(auth): prepare MSAL browser integration

This commit is contained in:
SaidSoighiri94
2026-07-23 13:38:20 +02:00
parent 530bd52cb5
commit ef31e2ab8c
8 changed files with 885 additions and 12 deletions
+8 -10
View File
@@ -37,7 +37,8 @@ class ApiClient {
late final http.Response reponse;
try {
reponse = await http.get(uri, headers: AuthService.requestHeaders());
final authHeaders = await AuthService.requestHeaders();
reponse = await http.get(uri, headers: authHeaders);
} catch (_) {
throw const ApiException(
"Impossible de joindre le serveur. Vérifiez que le backend est démarré.",
@@ -58,7 +59,8 @@ class ApiClient {
late final http.Response reponse;
try {
reponse = await http.get(uri, headers: AuthService.requestHeaders());
final authHeaders = await AuthService.requestHeaders();
reponse = await http.get(uri, headers: authHeaders);
} catch (_) {
throw const ApiException(
"Impossible de joindre le serveur. Vérifiez que le backend est démarré.",
@@ -82,12 +84,10 @@ class ApiClient {
late final http.Response reponse;
try {
final authHeaders = await AuthService.requestHeaders();
reponse = await http.post(
uri,
headers: {
...AuthService.requestHeaders(),
"content-type": "application/json",
},
headers: {...authHeaders, "content-type": "application/json"},
body: jsonEncode(body),
);
} catch (_) {
@@ -107,12 +107,10 @@ class ApiClient {
late final http.Response reponse;
try {
final authHeaders = await AuthService.requestHeaders();
reponse = await http.patch(
uri,
headers: {
...AuthService.requestHeaders(),
"content-type": "application/json",
},
headers: {...authHeaders, "content-type": "application/json"},
body: jsonEncode(body),
);
} catch (_) {
+49 -2
View File
@@ -1,3 +1,5 @@
import "msal_bridge.dart";
enum AuthenticationMode { demo, azure }
class AuthService {
@@ -17,6 +19,7 @@ class AuthService {
static const String demoResponsableEmail = "karim.benali@ensup.eu";
static String? _demoEmail;
static bool _azureInitialized = false;
static AuthenticationMode get mode {
return switch (_configuredMode) {
@@ -40,9 +43,31 @@ class AuthService {
_demoEmail = null;
}
static Map<String, String> requestHeaders() {
static Future<void> signInWithMicrosoft() async {
await _initializeAzure();
await MsalBridge.signIn();
}
static Future<bool> hasMicrosoftAccount() async {
await _initializeAzure();
return MsalBridge.hasAccount();
}
static Future<void> signOut() async {
if (mode == AuthenticationMode.azure) {
throw StateError("La session Microsoft n'est pas encore initialisee.");
await _initializeAzure();
await MsalBridge.signOut();
return;
}
clearSession();
}
static Future<Map<String, String>> requestHeaders() async {
if (mode == AuthenticationMode.azure) {
await _initializeAzure();
final token = await MsalBridge.getAccessToken();
return {"authorization": "Bearer $token"};
}
final email = _demoEmail;
@@ -53,6 +78,28 @@ class AuthService {
return {"x-user-email": email};
}
static Future<void> _initializeAzure() async {
if (mode != AuthenticationMode.azure) {
throw StateError("MSAL est disponible uniquement en mode Azure.");
}
if (_azureInitialized) {
return;
}
if (azureTenantId.isEmpty ||
azureSpaClientId.isEmpty ||
azureApiScope.isEmpty) {
throw StateError("La configuration Azure du frontend est incomplete.");
}
await MsalBridge.initialize(
tenantId: azureTenantId,
clientId: azureSpaClientId,
scope: azureApiScope,
redirectUri: Uri.base.origin,
);
_azureInitialized = true;
}
static void _ensureDemoMode() {
if (mode != AuthenticationMode.demo) {
throw StateError(
@@ -0,0 +1,56 @@
import "dart:js_interop";
@JS("emeMsal.initialize")
external JSPromise<JSAny?> _initialize(
JSString tenantId,
JSString clientId,
JSString scope,
JSString redirectUri,
);
@JS("emeMsal.signIn")
external JSPromise<JSAny?> _signIn();
@JS("emeMsal.getAccessToken")
external JSPromise<JSString> _getAccessToken();
@JS("emeMsal.hasAccount")
external JSBoolean _hasAccount();
@JS("emeMsal.signOut")
external JSPromise<JSAny?> _signOut();
class MsalBridge {
MsalBridge._();
static Future<void> initialize({
required String tenantId,
required String clientId,
required String scope,
required String redirectUri,
}) async {
await _initialize(
tenantId.toJS,
clientId.toJS,
scope.toJS,
redirectUri.toJS,
).toDart;
}
static Future<void> signIn() async {
await _signIn().toDart;
}
static Future<String> getAccessToken() async {
final token = await _getAccessToken().toDart;
return token.toDart;
}
static bool hasAccount() {
return _hasAccount().toDart;
}
static Future<void> signOut() async {
await _signOut().toDart;
}
}