Twilio Plugin - Keeping a user logged in

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.

Hi Nikita. Thank you for reaching out.

I only tested on Android.

The Twilio.loginWithCode(transactionID, code) returns a JSON user object that contains the whole User with the objectId. So I then call BackendlessUser.fromJson(value). This is the value I set as the current user. Will that not contain the objectId?

My code I tried here: Twilio Plugin - Keeping a user logged in - #16 by johan-jurrius

Regards

Yes, in this case the objectId must be contained in the current user’s object.
It looks like the problem is in the setUserToken method. Have you tried getting the token with getUserToken after setting it?

When the issue is fixed, I will let you know.

Yes, it receives the token 100%.

First line that starts with 4A38… is the token before I call setUserToken. Second line is the return of getUserToken.

If you want the project, I can send the whole project folder to you to test? Just not here. Nothing really in the project folder other than user authentication.

Regards

I just checked, the token is indeed set and returned, however loggedInUser returns an empty value. We’ll look into it, thanks.

Yes, exactly. Thank you very much! BUT normal Flutter SDK works 100% with loggedInUser. So wondered about that function where we send the true value to keep a user logged in. Something similar should be done maybe with the Twilio login.

I updated Flutter-SDK to version 7.1.9. Try something like this:

    await Backendless.userService
        .setUserToken(usertoken);
    user.setProperty('objectId', res!.getObjectId());
    await Backendless.userService.setCurrentUser(user, stayLoggedIn: true);
    result = await Backendless.userService.loggedInUser();
    print(result);

Best Regards, Nikita.

It seems to be working perfectly now. Excellent, thank you!

Can you maybe update the Twilio SDK for Flutter somewhere in the future? I would say we can have Twilio.loginWithCode(transactionId, code, stayLoggedIn). Then on the SDK side, when authenticated, the function can set the user token and the current user as you indicated. That would be awesome. BUT, it works as it is now. Thanks.

For others getting the same problem with Backendless 7.1.8 or lower, update to 7.1.9.

I did the following:

Twilio.loginWithPhoneNumberAndPassword(phone, password) returns a transactionId and sends sms for verification. I get the code via sms and send to:

Twilio.loginWithCode(transactionId, code) . This returns the authenticated user as a JSON object. I then call BackendlessUser.fromJson(value); to get the user as a BackendlessUser object.

I then call:

await Backendless.userService.setUserToken(value['user-token']);
            await Backendless.userService
                .setCurrentUser(_currentUser!, stayLoggedIn: true);

and send the user to the first screen. If any fails, user sees the login screen.

When my app then starts, I call:

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

If the validLogin is true, I call:

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

If that currentUserObjectId is also not null or empty, I call:

Map<dynamic, dynamic>? mapOfCurrentUser = await Backendless.data
            .of("Users")
            .findById(currentUserObjectId)
            .onError((error, stackTrace) {
          result = error.toString();
        });

to get the user that has been authenticated previously or that “stayLoggedIn”.

Thank you very much for the fast response and fixing the problem Nikita.

Regards