feat(auth): prepare MSAL browser integration
This commit is contained in:
@@ -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 (_) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user