Start a new topic
Answered

Is there any way to reset password with a SMS instead of email?

Hello. In order to reset their password, Kinvey sends an email to the stored email of the user. The problem I am facing is that my users do not have an email, but they have a phone number.


So is there any way I can handle the reset password request, so I could send an SMS with a temporary password from a custom endpoint?

I am thinking on sending the reset password email -from all the users- to a single predefined email, to open the email and click the link from some email-service API like Mailinator, then set a random password and send it by SMS to the user... but this looks very cumbersome.


Do you have any better idea?


Regards, Carlos


Best Answer

Carlos,


You can make a REST request from BL using the master secret, and updating the user entity with it..so basically a PUT request to update the user entity (setting the new password).


Thanks,

Pranav

Kinvey Support


Hi,


Here's an easier alternative:

  1. Instead of calling Kinvey's password reset method, call a business logic custom endpoint passing username.
  2. In the custom endpoint, find/fetch user object using master credentials (GET). Then, generate a random password by calling a random password generator (GET). Add password key-value to fetched user object and push it back to Kinvey with a update method (PUT). Then, send the new password to the customer's phone number as SMS using twilio.

Required resources:
One required condition is, Twilio should be able to deliver to your user's phone number.

Let me know if this helps.


Regards,
Wani


1 person likes this
Answer

Carlos,


You can make a REST request from BL using the master secret, and updating the user entity with it..so basically a PUT request to update the user entity (setting the new password).


Thanks,

Pranav

Kinvey Support


1 person likes this
Thank you Wani, I only have one problem. When calling the custom endpoint before being authenticated I got an `NoActiveUser` error. I do not find any way to call a custom endpoint without login first.
Do you know how can I workaround this?
Hi Pranav,
Thanks for your suggestion! I've made this function to update the user
function updateUser(user) {
  var context = modules.backendContext;
  var utils = modules.utils;
  
  var appKey = context.getAppKey();
  var masterSecret = context.getMasterSecret();
  
  var uri = 'https://' + request.headers.host + '/user/'+ appKey +'/' + user._id;
  var authString = "Basic " + utils.base64.encode(appKey + ":" + masterSecret);
  
  return modules.request.putAsync({
    uri: uri,
    headers: {
      "Authorization": authString,
      "Content-Type": 'application/json'
    },
    json: user
  });
}

 

 But for some reason I don't understand, after the user logs in, when tries to update his/her password, I got this error:

"InsufficientCredentials", "The credentials used to authenticate this request are not authorized to run this operation. Please retry your request with appropriate credentials".


So its seems that, after changing the password with the master secret, the user do not have the ability to change his/her own password. Is that possible?


Carlos

Hi,


Sorry I didn't consider this limitation while suggesting you my approach. There's no workaround for this.


A possible hack is to do a default user login just to execute that endpoint. But, that poses a potential security risk. So, I wouldn't recommend it.



Thanks,

Wani

Wani,

Related to my code, I need to set a new password. This is what I am doing now, but it doesn't seem to update the password (at least not the password I'm sending to the customer via SMS):
  var Promise = modules.bluebird;
  var twilio = modules.twilio(ACCOUNT_SID, AUTH_TOKEN);
  var sendSMSAsync = Promise.promisify(twilio.sendMessage, { context: twilio });
  var users = modules.collectionAccess.collection('user');

  return users.findOneAsync(queryCustomer)
  .then(function(customer) {
    if (!customer) throw 'There is no customer with that phone.';

    var temporaryPassword = generateRandomPassword();
    customer.password = temporaryPassword;
    return Promise.all([users.saveAsync(customer), temporaryPassword]);
  })
  .then(function(args) {
    var temporaryPassword = args[1];
    return sendSMSAsync({
      to: request.body.phone,
      from: FROMPHONE,
      body: 'Forgot your password? Your Temporal Password is "' + temporaryPassword + '"'
    });
  })
  .then(function(result) {
    response.body = result;
    return response.complete(200);
  }, function(err) {
    return response.error(JSON.stringify(err));
  });

The saveAsync function doesn't throw any error.

Is there a special way to change a password from Business Logic?


Regards, Carlos

Actually the code is just fine. The last problem I had it was trying to save a relational data that the user had no permission. Thanks for all the help :)

 

Login or Signup to post a comment