feathersjs-ecosystem / feathers-authentication-management

Adds sign up verification, forgotten password reset, and other capabilities to local feathers-authentication
https://feathers-a-m.netlify.app/
MIT License
246 stars 98 forks source link

sendResetPwd token storage #152

Closed bwgjoseph closed 4 years ago

bwgjoseph commented 4 years ago

Hi,

When you create a new user, you will get something like this store in the db

{
    "_id" : ObjectId("5f23002078128c11e8f3d1b0"),
    "email" : "bbbbbbbbbb@ainbz.com",
    "password" : "$2a$10$FcMIsxQrCGYuPqi6GXreyOU6WpCr8LIm0P9OVBAXhF.W5XupPFK32",
    "isVerified" : false,
    "verifyExpires" : ISODate("2020-08-04T17:15:12.234Z"),
    "verifyToken" : "e4d0469048d3234222e7ad33c3ba36", // notice the token is just a string
    "createdAt" : ISODate("2020-07-30T17:15:12.241Z"),
    "updatedAt" : ISODate("2020-07-30T17:15:12.241Z"),
    "__v" : 0
}

This is what you will get in the email as the link - http://localhost:3030/verify?token=e4d0469048d3234222e7ad33c3ba36 Single token length

Now, if you perform a sendResetPwd to /authmanagement endpoint.. This is what is stored..

{
    "_id" : ObjectId("5f23002078128c11e8f3d1b0"),
    "email" : "bbbbbbbbbb@ainbz.com",
    "password" : "$2a$10$FcMIsxQrCGYuPqi6GXreyOU6WpCr8LIm0P9OVBAXhF.W5XupPFK32",
    "isVerified" : true,
    "verifyExpires" : null,
    "verifyToken" : null,
    "createdAt" : ISODate("2020-07-30T17:15:12.241Z"),
    "updatedAt" : ISODate("2020-07-30T17:17:07.981Z"),
    "__v" : 0,
    "resetExpires" : ISODate("2020-07-30T19:17:07.722Z"),
    "resetToken" : "$2a$10$nVx6nn/8gqlZv7YJWSOQMeZgElqKU4a3BmjnTNksvlzfOY8pHsjp6" // see this token is encrypted
}

This is what you will get in the email as the link - http://localhost:3030/reset?token=5f23002078128c11e8f3d1b0___1186cc1f36b288ddc6d43ee893b7b9 Seem like double token length?

Is this action intentionally? If so, why is that? Or is it that my configuration is wrong?

Thanks!

claustres commented 4 years ago

Hi, yes I think it's intentional. The verify operation is expected to be performed once the user is authenticated so that it is already identified in the system and more particularly in hooks. However, reset operations can be done without the user be authenticated (eg lost password) so that the first part of the token is actually the user ID used to identify it.

There might also be some security reason about hashing the token in the second case. Probably that if a hacker has access to your DB he could probably trigger the reset operation without access to the email while if hashed he will not be able to do that.

Close if it's clear for you.

bwgjoseph commented 4 years ago

The verify operation is expected to be performed once the user is authenticated so that it is already identified in the system and more particularly in hooks

hmm, this doesn't seem true. I can verify even if I'm not authenticated unless I understand wrongly?

claustres commented 4 years ago

You are right, the problem is that in the second case as the token is hashed so you cannot just find it in the DB like in the verification case so that you need a user ID in addition.

bwgjoseph commented 4 years ago

Yup, agree on the additional security there. Just want to understand the rational.

Just that I don't misunderstand you, when you mentioned so that you need a user ID in addition, you meant for verifySignupLong flow?

I do not need to pass in userId when verifying the signup, or were you referring to 5f23002078128c11e8f3d1b0___1186cc1f36b288ddc6d43ee893b7b9 where the first part is the userId hashed?

claustres commented 4 years ago

Yes I am referring to the second use case.

bwgjoseph commented 4 years ago

Thanks for the clarification!