loginWithMicrosoft method

  1. @override
Future<Map<Object?, Object?>?> loginWithMicrosoft({
  1. required String tenantId,
  2. required String clientId,
  3. String? clientSecret,
  4. required String redirectUrl,
  5. required String scope,
  6. String? tokenScope,
  7. String? nonce,
})
override

Implementation

@override
Future<Map<Object?, Object?>?> loginWithMicrosoft({
  required String tenantId,
  required String clientId,
  String? clientSecret,
  required String redirectUrl,
  required String scope,
  String? tokenScope,
  String? nonce,
}) async {
  final authUrl = _buildAuthorizationUrl(
    tenantId: tenantId,
    clientId: clientId,
    redirectUrl: redirectUrl,
    scope: scope,
    nonce: nonce,
  );

  // Open popup
  final popup = web.window.open(
    authUrl,
    'MicrosoftAuth',
    'width=800,height=600',
  );
  if (popup == null) {
    throw Exception(
      'Could not open popup window. Please allow popups for this site.',
    );
  }

  final completer = Completer<String>();
  late Timer timer;
  timer = Timer.periodic(const Duration(milliseconds: 500), (t) {
    if (popup.closed) {
      timer.cancel();
      if (!completer.isCompleted) {
        completer.completeError(
          Exception('User closed the authentication window.'),
        );
      }
      return;
    }

    try {
      final currentUrl = popup.location.href;
      if (currentUrl.startsWith(redirectUrl)) {
        final uri = Uri.parse(currentUrl);
        if (uri.queryParameters.containsKey('code')) {
          timer.cancel();
          popup.close();
          completer.complete(uri.queryParameters['code']);
        } else if (uri.queryParameters.containsKey('error')) {
          timer.cancel();
          popup.close();
          final errorMsg =
              uri.queryParameters['error_description'] ??
              uri.queryParameters['error'];
          completer.completeError(Exception(errorMsg));
        }
      }
    } catch (e) {
      // Cross-origin access throws an error until redirected back to the same origin.
    }
  });

  try {
    final code = await completer.future;

    return await exchangeCodeForToken(
      tenantId: tenantId,
      clientId: clientId,
      clientSecret: clientSecret,
      code: code,
      redirectUrl: redirectUrl,
      scope: tokenScope,
    );
  } catch (e) {
    return Future.error(e);
  }
}