Twilio Plugin - Keeping a user logged in

This is my whole function:

Future<String> checkIfUserLoggedIn() async {
    String result = 'OK';

    bool? validLogin = await Backendless.userService
        .isValidLogin()
        .onError((error, stackTrace) {
      result = error.toString();
    });

    if (validLogin != null && validLogin) {
      String? currentUserObjectId = await Backendless.userService
          .loggedInUser()
          .onError((error, stackTrace) {
        result = error.toString();
      });
      if (currentUserObjectId != null) {
        Map<dynamic, dynamic>? mapOfCurrentUser = await Backendless.data
            .of("Users")
            .findById(currentUserObjectId)
            .onError((error, stackTrace) {
          result = error.toString();
        });
        if (mapOfCurrentUser != null) {
          _currentUser = BackendlessUser.fromJson(mapOfCurrentUser);
          notifyListeners();
        } else {
          result = 'MAP IS NULL';
        }
      } else {
        result = 'USER OBJECT ID IS NULL';
      }
    } else {
      result = 'NOT VALID LOGIN';
    }

    return result;
  }

It returns MAP IS NULL…narrowed it down…validLogin is true but currentUserObjectId is empty.

sorry but according to our support policy we do not debug customer’s code, could you please minimize your sample to show problem with the Backendless API

If I login a user, my app takes me to the first screen successfully.

If I run the app again…

This code:

bool? validLogin = await Backendless.userService
        .isValidLogin()
        .onError((error, stackTrace) {
      result = error.toString();
    });

returns true, 100% as it should.

If I login the user again, and use the logout call, and run the app again, the function above returns false. Again 100% correct.

My problem comes in at the next step.

This code then:

String? currentUserObjectId = await Backendless.userService
          .loggedInUser()
          .onError((error, stackTrace) {
        result = error.toString();
      });

returns an empty currentUserObjectId if isValidLogin() is true. That is my problem. And it does not go into the error section. Just returns an empty value. I have used this exact function many times before using the normal Flutter SDK that uses the true value to stay logged in. Twilio SDK is not keeping the user logged in or something. But, still seems it picks up there is a valid login. Just cannot get the one logged in?

Ok, I see

I’ve created an internal ticket BKNDLSS-27495 to investigate this case, our Flutter engineer will take a look as soon as it only possible

Thank you. I have tried both:
Backendless.userService.setCurrentUser(user)
and
Backendless.userService.setUserToken(userToken)

and both gives the same value of validLogin as true, but returns empty currentUserObjectId (in my function)

Future loginUser(String phone, String password,
      TextEditingController codeController) async {
    String result = 'OK';
    FocusManager.instance.primaryFocus?.unfocus();
    _showUserProgress = true;
    _userProgressText = 'Busy logging you in...please wait...';
    notifyListeners();
    phone = phone.replaceRange(0, 1, '+27');
    print(phone);
    Twilio.loginWithPhoneNumberAndPassword(phone, password).then((value) async {
      String transactionId = value["transactionId"];
      String? code = await showVerificationDialog(codeController);
      if (code != null && code.compareTo('CANCEL') != 0) {
        Twilio.loginWithCode(transactionId, code).then((value) {
          if (value != null) {
            print(value);
            _currentUser = BackendlessUser.fromJson(value);
            //Backendless.userService.setCurrentUser(_currentUser!);
            print(value['user-token']);
            Backendless.userService.setUserToken(value['user-token']);
          }
          _showUserProgress = false;
          notifyListeners();
          Get.off(() => const HomeAdmin());
          showSnackBar(
              title: 'User Authentication',
              message:
                  '${_currentUser == null ? 'User' : _currentUser!.email} successfully authenticated!');
        }).onError((error, stackTrace) {
          print(getHumanReadableError(error.toString()));
          showSnackBar(title: 'User Authentication', message: error.toString());
          _showUserProgress = false;
          notifyListeners();
        });
      } else {
        showSnackBar(
            title: 'Authenticate User',
            message: 'Sorry, could not verify your phone number.');
        _showUserProgress = false;
        notifyListeners();
      }
    }).onError((error, stackTrace) {
      print(getHumanReadableError(error.toString()));
      showSnackBar(title: 'Here Authenticate User', message: error.toString());
      _showUserProgress = false;
      notifyListeners();
    });
  }

My login function. Like I said, login works perfectly, but the User does not stay logged in when using the normal Flutter SDK to check.

yeah, seems like the issue is on our side in the FlutterSDK

Thank you

for now, as a workaround, I can propose you use your solution after login keep the token in the storage on your device and on app start set the value to the SDK

Will try that thanks. Also, to be clear, the Flutter SDK works 100% as it is. The Twilio Flutter SDK needs tweaking. So I was using the Twilio Flutter SDK to login a user but the normal Flutter SDK to check the login. Without Twilio, normal login and keeping a user logged in works 100%. Would be nice to just set a stayLoggedIn field as part of one of the login functions of the Twilio Flutter SDK. Also, the Twilio deployed service under Cloud Code does not have that option either. So it could be wider than Flutter? Otherwise I could just invoke the cloud code?

Regards

Twilio Plugin is just an API Service, so it doesn’t have access to your local device, and the Twilio Plugin SDK is just a client for running the API Service

Ok thanks for the info.

I did the following: At successful login, I save the user token to the phone. When the app restarts, I get the user token and call Backendless.userService.setUserToken(userToken). Just before this statement I print out the user token and it shows perfectly. After this statement I call Backendless.userService.loggedInUser(). This function returns an empty objectId again. So for now maybe I will save the objectId to get the logged in user instead of the token?

Another question. Twilio works on the Cloud 99 trial plan (except for keeping the user logged in). I also have the free Springboard plan. There the plugin registers a user 100%, but when I try to login, it says a user with that number does not exist, even though the user is there. Is this a limitation of the Springboard plan as everything else is exactly the same?

hello @johan-jurrius

The Springboard plan does not have any limitations for login. It works in the same way as on any plan.

Thank you for your answer. I have a mobile app developed in Flutter. I also have 2 Backendless Apps. One on Cloud 99 (trial) and one on Springboard. I move between apps by just changing the api keys and appID in my client. The app can login a user on Cloud 99 but not on Springboard. In Springboard it says the telephone number does not exist. I do have the field “'phoneNumber”’ in the Users table for both. Works in Cloud 99 and not in Springboard. Any idea why? On both it registers a User in the Users table with the correct phone number and Twilio codes being sent and authenticated.

@johan-jurrius please provide your application’s ids

On this one it works fine: 075F9883-1E98-6218-FFAC-FCEFBC95B000 (Cloud 99 on a different account)
On this one it does not work: 725521A2-5598-4241-FFA2-897A0E52B700 (Springboard plan before Backendless subdomains has been introduced) - Could this be the problem?

@johan-jurrius looks like everything is the same…

Also I was not able to reproduce the issue in your Fibre app I have created test user with phoneNumber, try to login and get {"transactionId":"SM58064226d697479397940077c32ea725"}

Thank you for confirming. I am using the loginWithPhoneNumberAndPassword() function of the Flutter Twilio SDK. On the Cloud 99 plan I get the transactionId returned. On Springboard I don’t. It fails with “BackendlessException: There is no user with provided phone number, code = 0” I will create a video to show you. Exact same code. Not sure what is going on.

Stupid mistake from my side. I had some Security Roles that were limiting access. All working now. Thank you so much for trying to assist.

Don’t mark this as solved yet, still waiting on internal ticket: BKNDLSS-27495

Regards

Hello, @johan-jurrius.

I would like to clarify some questions.
On which platforms is the error observed (iOS, Android, Web)?

And regarding your answer, when setting setCurrentUser make sure you include an objectId. It should look something like this:

    await Backendless.userService.setUserToken('35785ADA-7D28-4EDE-87AF-FE7BD21FF948');
    BackendlessUser user = BackendlessUser();
    user.setProperty('objectId', '00EF6D52-10C7-464F-AD86-AA2F82C342F4');//IMPORTANT
    user.setProperty('phone', '12322');
    user.setProperty('name', 'John Dow');
    await Backendless.userService.setCurrentUser(user);

Best Regards, Nikita.