10

I need help for creating the REST endpoints. There are couple of activities :

To change the email there are 3 URL requests required:

  1. /changeemail : Here one time password (OTP) is sent to the user's mobile

  2. /users/email : the user sends the one time password from previous step and system sends the email to the new user to click on the email activate link

  3. /activateemail : user clicks on the link in the new email inbox and server updates the new email

To change password :

  1. /users/password (PATCH) : user submits old password and new password and system accordingly updates the new password

Similarly, there are other endpoints to change profile (field include bday, firstname and last name)

after reading online I believe my system as only users as the resource --> so to update the attributes I was thinking of using a single PATCH for change email and change password and along with that something like operation field so the above two features will look like :

For changing email :

  1. operation : 'sendOTPForEmailChange'
  2. operation : 'sendEmailActivationLink'
  3. operation : 'activateEmail'

For changing password :

  1. operation : 'changePassword'

and I will have only one endpoint for all the above operations that is (in nodejs) :

app.patch('/users', function (req, res) {
  // depending upon the operation I delegate it to the respective method
   if (req.body.operation === 'sendOTPForEmailChange') {
       callMethodA();
   } else if (req.body.operation === 'sendEmailActivationLink') {
     callMethodB();
   } else if (req.body.operation === 'activateEmail') {
      callMethodC();
   } else if (req.body.operation === 'changePassword') {
      callMethodC();
   } else sendReplyError();

});

Does this sound a good idea ? If not, someone can help me form the endpoints for changeemail and changepassword.

Answer :

I finally settled for using PATCH with operation field in the HTTP Request Body to indicate what operation has to be performed. Since I was only modifying a single field of the resource I used the PATCH method. Also, I wanted to avoid using Verbs in the URI so using 'operation' field looked better.

Some references I used in making this decision :

Wilts answer link here

Mark Nottingham' blog link article

and finally JSON MERGE PATCH link RFC

Community
  • 1
  • 1
j10
  • 2,009
  • 3
  • 27
  • 44
  • Am using nodejs with routes, controllers and models and have a database for changing email requests codes generated which are send as email to the users. How would the above example look like in terms of routes and controller – j10 Jul 21 '17 at 08:32
  • Similarly even for editing profile I will use same endpoint like /users/:user_id and operation : getProfile. – j10 Jul 21 '17 at 10:07

3 Answers3

4

You should make the links that define the particular resource, avoid using PATCH and adding all the logic in one link keep things simple and use separation of concern in the API like this

1- /users/otp with HTTP Verb: GET -> to get OTP for any perpose
2- /users/password/otp with HTTP Verb: POST -> to verify OTP for password and sending link via email
3- /users/activate with HTTP Verb: POST to activate the user
4- /users/password with HTTP Verb: PUT to update users password
Ghulam Mohayudin
  • 1,093
  • 10
  • 18
  • I don't think its a good idea to use verbs in URI for e.g. - activate. Also, for Password there are 2 cases like Change password (User remembers the old password) and Reset Password (User does not remember the old password) so URI '/users/password' will not be much helpful. I decided to use patch because I was only updating a part of the resource 'user' Checkout Selvamani's answer here : [link here](https://stackoverflow.com/questions/21660791/what-is-the-main-difference-between-patch-and-put-request) – j10 Jul 28 '17 at 06:02
  • I went with PATCH for all the operations and I added a operation field to the Request body. Something similar to concept of JSON Merge Patch [link here](https://tools.ietf.org/html/rfc7386) – j10 Jul 28 '17 at 06:04
  • I think you should read this PATCH is not for this purpose "The difference between the PUT and PATCH requests is reflected in the way the server processes the enclosed entity to modify the resource identified by the Request-URI. In a PUT request, the enclosed entity is considered to be a modified version of the resource stored on the origin server, and the client is requesting that the stored version be replaced. With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version" – Ghulam Mohayudin Jul 28 '17 at 06:08
  • 1
    You are simply modifying the resource you are not telling the server how to modify this resource, PATCH is a way to tell server how to modify a particular resource – Ghulam Mohayudin Jul 28 '17 at 06:13
  • 1
    I believe in PUT you will have to share the entire resource representation and it will be replaced completely on the server with the old resource representation. For PATCH you mention what you want to modify and only that part changes (to save bandwidth) Also, check Wilt's answer [link here](https://stackoverflow.com/questions/3077229/restful-password-reset/33389526?noredirect=1#comment77332886_33389526) in comments we agreed the operation should have been PATCH and not PUT. – j10 Jul 28 '17 at 06:14
  • checkout the JSON Merge PATCH RFC on how the client indicates to the server - change in the new values -- it just sends the new values and fields which have to be removed are send using 'null' – j10 Jul 28 '17 at 06:18
  • In the previous link that you shared, Darrel Miller have accepted POST or PUT as the more suitable way to do this – Ghulam Mohayudin Jul 28 '17 at 06:25
  • But if you have made your mind to go with PATCH its also good but adding all the logic into one resource is not a good idea. – Ghulam Mohayudin Jul 28 '17 at 06:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/150369/discussion-between-jitenshah-and-ghulam-mohayudin). – j10 Jul 28 '17 at 06:33
2

Hashing Security is a must read, IMHO, should you ever want to implement your own user account system.
Two-factor identification should always be considered, at least as an opt-in feature. How would you integrate it into your login scheme ?
What about identity federation ? Can your user leverage their social accounts to use your app ?

A quick look at Google yielded this and this, as well as this.

Unless you have an excellent reason to do it yourself, I'd spend time integrating a solution that is backed by a strong community for the utility aspects of the project, and focus my time on implementing the business value for your customers.

NB: my text was too long for the comments

Sumi Straessle
  • 1,116
  • 12
  • 23
  • 2
    Thank you Sumi for sharing the links. I am using bcrypt and at this moment we are not considering Social Media Accounts. Sumi, you should split up your comments if they are long because if no one answers the question - bounty will be awarded to you and your answer does not help me with my question . – j10 Jul 27 '17 at 08:41
  • I understand your points on comment but I disagree with the fact that my answer doesn't help you. I pointed you to a library interaction direction which a lot of people would agree is the better approach since you can focus on your core business and rely on a community that solves a common issue. As to bcrypt, state of the art today is Argon which has won the hashing algorithm competition. I would however use PBKDF2 with SHA256 or SHA512, since it is battle tested. This time tested argument is important in the context of security (do you remember HeartBleed?) – Sumi Straessle Jul 27 '17 at 17:12
  • Sumi, I was earlier advised by SO community to use standard Auth Provider Service but they seem to be expensive. Since, we had decided to implement it ourselves at least for the start - I was looking for the answer to the question. May be I should have clarified that in the question. Definitely knowledge you shared was helpful :) – j10 Jul 28 '17 at 06:07
  • Context is important. – Sumi Straessle Jul 28 '17 at 06:47
1

Mostly agree with Ghulam's reply, separation of concerns is key. I suggest slightly different endpoints as following:

1. POST /users/otp      -> as we are creating a new OTP which should be returned with 200 response. 
2. POST /users/email    -> to link new email, request to include OTP for verification. 
3. PUT  /users/email    -> to activate the email.
4. PUT  /users/password -> to update users password.
Deven Shah
  • 396
  • 2
  • 5
  • You are right but I do not agree with this link because it does not describe resource itself, it should describe that it will perform an operation verifying otp and sending email of password. users/email doesn't describe that it will generate an email for password and any link to otp – Ghulam Mohayudin Jul 27 '17 at 17:44
  • @Deven : Please check my reply to Ghulam's answer. – j10 Jul 28 '17 at 06:07