login method

Future<AuthResult> login({
  1. bool forceLogin = false,
})

Logs the user Forces the user to enter their credentials to ensure the correct users account is authorized.

Implementation

Future<AuthResult> login({bool forceLogin = false}) async {
  String? resultURI;
  RequestToken requestToken;
  try {
    requestToken = await RequestToken.getRequestToken(
      apiKey,
      apiSecretKey,
      redirectURI,
      forceLogin,
    );
  } on Exception {
    throw PlatformException(
      code: '400',
      message: 'Failed to generate request token.',
      details: 'Please check your APIKey or APISecret.',
    );
  }

  final uri = Uri.parse(redirectURI);
  final completer = Completer<String?>();
  late StreamSubscription<void> subscribe;

  if (Platform.isAndroid) {
    await _channel.invokeMethod('setScheme', uri.scheme);
    subscribe = _eventStream.listen((data) async {
      if (data['type'] == 'url') {
        if (!completer.isCompleted) {
          completer.complete(data['url']?.toString());
        } else {
          throw const CanceledByUserException();
        }
      }
    });
  }

  final authBrowser = AuthBrowser(
    onClose: () {
      if (!completer.isCompleted) {
        completer.complete(null);
      }
    },
  );

  try {
    if (Platform.isIOS || Platform.isMacOS) {
      /// Login to Twitter account with SFAuthenticationSession or ASWebAuthenticationSession.
      resultURI = await authBrowser.doAuth(requestToken.authorizeURI, uri.scheme);
    } else if (Platform.isAndroid) {
      // Login to Twitter account with chrome_custom_tabs.
      final success = await authBrowser.open(requestToken.authorizeURI, uri.scheme);
      if (!success) {
        throw PlatformException(
          code: '200',
          message: 'Could not open browser, probably caused by unavailable custom tabs.',
        );
      }
      resultURI = await completer.future;
      await subscribe.cancel();
    } else {
      throw PlatformException(
        code: '100',
        message: 'Not supported by this os.',
      );
    }

    // The user closed the browser.
    if (resultURI?.isEmpty ?? true) {
      throw const CanceledByUserException();
    }

    final queries = Uri.splitQueryString(Uri.parse(resultURI!).query);
    if (queries['error'] != null) {
      throw Exception('Error Response: ${queries['error']}');
    }

    // The user cancelled the login flow.
    if (queries['denied'] != null) {
      throw const CanceledByUserException();
    }

    final token = await AccessToken.getAccessToken(
      apiKey,
      apiSecretKey,
      queries,
    );

    if ((token.authToken?.isEmpty ?? true) || (token.authTokenSecret?.isEmpty ?? true)) {
      return AuthResult(
        authToken: token.authToken,
        authTokenSecret: token.authTokenSecret,
        status: TwitterLoginStatus.error,
        errorMessage: 'Failed',
      );
    }

    User? user;

    try {
      user = await User.getUserData(
        apiKey,
        apiSecretKey,
        token.authToken!,
        token.authTokenSecret!,
      );
    } on Exception {
      debugPrint('The rate limit may have been reached or the API may be restricted.');
    }

    return AuthResult(
      authToken: token.authToken,
      authTokenSecret: token.authTokenSecret,
      status: TwitterLoginStatus.loggedIn,
      user: user,
    );
  } on CanceledByUserException {
    return AuthResult(
      status: TwitterLoginStatus.cancelledByUser,
      errorMessage: 'The user cancelled the login flow.',
    );
  } catch (error) {
    return AuthResult(
      status: TwitterLoginStatus.error,
      errorMessage: error.toString(),
    );
  }
}