I’m working on iOS and Android apps and I have a scenario where user needs to change their username. I’d like to protect this operation with current password so only users who now the password can do this.
So after user inputs the required data (current password and new username) it’s required to check if the password is correct. The only way I’ve found to check the password is to actually login the user again using the entered password. If login is successful I then update current user object.
Though the flow above seems to work I’ve run into an issue.
Because of the additional login I get the following error every time I try to perform any further fetch operations (note: multiple login is enabled):
FAULT = ‘3064’ [Not existing user token - XXX. Relogin user to update your user token] <Not existing user token - XXX. Relogin user to update your user token>
One dirty workaround is once the update operation from above is completed, is to logout user and to login them again as part of the update operation. In this case I have to perform calls as the following:
login in order to check if the password is correct
logout user and login again to make sure token is correct (please note, I can’t call logout before the first login since user may enter incorrect password which will lead to logout user state)
perform actual password protected operation (username updating in this case)
What is the correct way to handle scenarios when password protection is required in order to perform any specific actions in the app?
Does the error with the non-existing user token happen for the update operation? (you mention it happens for the fetch operations). I am trying to reconstruct the flow so I can understand at what point the token becomes invalid:
User logs in
User updates a password-protected property
App checks if the password is valid and logs the user in again
If (3) is successful, the app updates the user object
App fetches something from the server and the request fails with the non-existing user token error
Is this correct?
Yes, that’s correct - update operation completes successfully in the mentioned flow and the error is only appears once I try to fetch any data afterwards.
Let me know if I can provide any additional information on this.
I think I know what’s going - the use update operation invalidates the existing user token. I will double check with the dev team to find out for sure.
As a workaround, you could duplicate the user password in an additional property. It it is stored there too (in addition to the standard “password” property), then you would be able to check if the password is valid with a simple “find” request. The down side of this approach is the user password would also be stored in clear text.
Thinking more about it, the approach with storing the password in an additional property could work quite well. And the password does not need to be in clear text. Your app could encode the password value any way you want to and store the encoded value. Then when you need to validate the password - you would apply the same encoding algorithm and then run a query in Backendless for the encoded value.
I thought the problem is in updating operation as well. But I have other profile fields which is possible to update without entering password and it appeared that it works fine - for example it’s possible to update first name and last name which are also stored in user object as additional properties and they are not password protected. Fetch operations are still working as expected after that. So I’ve narrowed down to the extra login part which seems to cause the issue.
Thanks for your input regarding password approach - I wanted to avoid storing it in any way though storing encoded value might work. I just need to think of a good approach on this to ensure security which is quite a concern.
It would be great to have a way to check password using the SDK to ensure sensitive operations are performed by security professionals which is backendless team - I’m not quite proficient in this so just doubt if I might run into any security leaks with the chosen approach if I’ll do it my side
How do you update the user object? Is it with Backendless.UserService.update or with Backendless.Data.of( BackendlessUser.class ).update? (I am assuming you use Android).
I’ve tried the code and the user token is always an empty string i.e. userToken == “”
Just a note - I login user with Backendless.UserService.login(email, password) and then execute any relevant operations in the app (like fetch, update)
Let me know if I can provide any additional information.
Not sure I understand what you mean by ‘login outside of the app’ but all the backendless related operations are executed inside the app. So the flow is:
user opens the app
user provides their credentials to login
Backendless.UserService.login(email, password) is executed
if login successful user is redirected to the main screen
from there user can request any data that may require backendless related operations (fetch, update)
during all this process token is an empty string (according to the UserTokenStorageFactory.instance().getStorage().get()) though fetch/update requests are executed as expected
once I execute additional login (for password protected operations) and update user data the subsequent fetch/update operations fails with “Not existing user token”
I’ve also noticed that sometimes it’s a different error when trying to execute any operation after the “protected field change flow” (from handleFault() callback):
BackendlessFault{ code: 'IllegalArgumentException', message: 'Attempt to invoke virtual method 'java.lang.String com.backendless.Footprint.get__meta()' on a null object reference' }
In your update() call, do you also send the ‘password’ field? That could explain the user-token invalidation, since it would be perceived as a password update.
OK, could you then please provide a code sample with the operations sequence you described and note which line throws an error, so that we could try to reproduce the behaviour?