I'm working on designing Restful API for forgot password flow.
The flow to be used in web application is below:
1) User enters user id
2) Application validates user id and sends verification token to user's email address
3) User will be asked for validation code and new password
4) User will enter validation code and new password
5) Application validates token and updates password.
I would appreciate your suggestions on how this flow can be translated to Restful API's.
Thank you,
Raj
This is a very standard design, I think you can find lots of resources, or even reset your own password on some website and see how that works.
The basics:
The client will make a POST request when sending the user id. Note that it's a good idea to NOT say if the user id / email is valid (to avoid brute force checking of user id / email existing). Also, make it so that you can't request another password reset until the previous token has expired (to prevent DoS attacks).
As you said, the server will check the associated email and eventually send the token.
There is no actual need for the user to enter the validation token. Just like most sites do, you can embed that in the link that you send in the email. Remember to set a reasonable expire time for the token (maybe one hour?). Here you should already check the token validity.
The link with the token will be a GET request to a specific page where the user is automatically authenticated and can enter the new password (again: remember the expiry time on the token).
The user will enter the new password with a POST request, you check the token validity again, and if everything matches, you update the password.
In terms of POST and GET calls that can be something like:
POST https://www.yoursite.com/resetpassword, with the user id / email in the body. Don't put the user id / email as a query or path parameter, especially if you have ads / banners on the page, because they might be able to get that data.
GET https://www.yoursite.com/password?token=dhs3541hpk43hokdsau9ef where the token is associated with the user id / email resetting the password (you should have this in a database). Here the token is validated for the first time and the user can enter the new password in a form. Note that this can be the same form that you use when the user is changing the password, just without the Old password field. Note that you should NOT have banners / ads on this page, ever. That would be a serious security risk.
POST https://www.yoursite.com/password?token=dhs3541hpk43hokdsau9ef with the new password in the body. Again, don't put banners / ads on this page. The server will check the token again and if it matches, update the password. Then the server will mark the token as invalid / expired.
Related
I am currently using a client-side React component to have a user login to Facebook via OAuth in my application. On the server-side, I use the npm package passport-facebook-token to validate the authenticity of the accessToken after a successful client-side login.
One practice I do not see often is in addition to asking Facebook if the accessToken is valid, shouldn't the server also check if the email provided by the client's payload matches the e-mail coming back from Facebook? Allow me to use defined client/server technologies to illustrate my question:
1) User uses React component on the client to authenticate with Facebook.
2) React component successfully authenticates with Facebook and fires an HTTP request to the server with an access token and the user's email.
3) The server, running Node.JS and passport-facebook, now needs to verify the authenticity of the access token directly from Facebook. Facebook does not care for an e-mail. It will just verify the access token.
4) Facebook returns a response to Node.js confirming the authenticity of the access token. The response also contains other metadata about the user, including their email and other profile data.
My question is, should Node.js take the email that's also coming back from Facebook's access token verification payload, and verify that it is what came back from the React client? Would this not prevent someone from brute-forcing an accessToken and require them to not only have an accessToken but also know who the accessToken belongs to? This could prevent a user from submitting a bunch of HTTP POST requests to the Node.js server attempting different access tokens. They would not only have to guess an access token assigned to the application's clientID, but also know the e-mail it belongs to. Is this an over-engineered approach?
Really the best way I can think of to make your OAuth accessToken and 'code' value less prone to brute-forcing is using a Cryptographic Number Generator to create a 128-bit length string of random data and encoding it with base 64 to use as your code. It's extremely unlikely that it would be guessed by a computer or by someone redirecting to and from the authorization endpoint and the redirect-uri with query parameters.
Another method of fortification is limiting the rate of authorizations by IP address (which you can do instead of email through Node.js) but that is usually not a problem for most well-equipped hackers. I highly advise the first method for creating a more secure service.
Your approach to validate the email as well as the token is a bit superfluous because Facebook's opaque user access tokens are inherently tied to email.
From Facebook
An access token is an opaque string that identifies a user, app, or Page
"opaque" is defined by Auth0 here
Opaque Access Tokens are tokens in a proprietary format that typically contain some identifier to information in a server’s persistent storage
In your case, the identifier is the user's email, and the server belongs to Facebook.
I will elaborate further. Here is your step by step with some edits:
User uses React component on the client to authenticate with Facebook, inputting both their email and password directly to Facebook. React component gets the token from Facebook on login success.
React component successfully authenticates with Facebook and fires an HTTP request to the server with an access token and the user's email.
The server, running Node.JS and passport-facebook, now needs to verify the authenticity of the access token directly from Facebook. Facebook does not care for an e-mail. It will just verify the access token because the access token is already tied to the email.
Facebook returns a response to Node.js confirming the authenticity of the access token. The response also contains other metadata about the user, including their email and other profile data.
This is Facebook's bug bounty program. If their OAuth was really as cracked as to require a second email validation, it would have been patched almost immediately by this incentive.
I'm looking for the correct way to customize or extend identityserver3 to implement passwordless authentication.
the user scenario is
user uses browser to go to website
website detects non-authenticated
user and redirects to idsrv3 instance
idsrv3 asks for email address (or uses a cookie stored one) and if email address matches a known user, sends an email with a link (e.g. like the registration or password reset link)
user clicks on link
idsrv3 instance checks if token in link matches a known user and is not expired
idsrv3 issues token
idsrv3 redirects to original url
after some reading, I think the correct way to customize idsrv3 would be to
create a custom viewservice
checks the emailaddress
generates and stores a token in the user account record
sends an email with a link consisting of a custom grant, the token and a returnurl
create a custom grant and corresponding validator
checks the incoming token and if valid returns a positive validation result linked to a user account
the normal idsrv3 token issuing flow takes over to issue a token and redirect to the returnurl
In my experience, idsrv3 is great, but it can be time-consuming to get things right when customizing and I would like to be sure that I don't hit a brick wall somewhere near the end of the solution.
Our application uses oauth2 & openid connect for auth&auth. It's built using an angular client that calls a REST API. I would like to know how to authorize access to the API, based on the possession of an unguessable url.
I'll explain this a little more. In the application, a user can invite another user. When this happens, an email is sent to the second user. When user 2 clicks a link in the email, he is sent to a webpage with details about the invitation.
Only user 2 should be allowed to see the invitation page. I was planning to solve this by using an 'unguessable url' in the email. Upon visiting the url, the user must somehow be authorized to fetch the invitation details from the API.
The question: how do I authorize a user, based on knowing the unguessable url? How do I assign a claim when the page is loaded, and how do I verify this claim in the API call that follows? The only solution I see, is to set a cookie containing a token. But this is not in line with our existing auth mechanism. I prefer not writing my own token validation code, and let the Identity Provider handle this.
Additional info: user 2 may or may not have an account in the system, and he may or may not be logged in. Neither should prevent the user from seeing the invitation details. In other words: a totally unknown user should be able to see the page. The knowledge of the url should be the only requirement.
Any solution to this problem? Or am I handling it all wrong?
After asking around, the general consensus is to NOT let the external auth mechanism take care of this, but to validate the link ourselves.
The solution is to turn the unguessable part of the url (the 'link id') in some kind of token, which can be validated upon calling the API. This is done by the API itself, not by the Identity Server.
Applied to the invitation issue: when an invitation is created, store the link id together with some info, i.e. what kind of access it allows (invitation access) and the id of the invitation. When the user calls the API to get the invitation, pass the link id for validation. Match the invitation id with the invitation id stored in the link, and if it doesn't, throw an error.
I have to develop a Rest API for forgot password functionality which span in three different workflow i.e.
First I need to verify user input for name, email and phone. If all are valid and belongs to that particular user, will send some security code to user's email and phone.
If first step is success. Need to capture security codes(from email and phone) provided by user and validate those.
If second step is success. Capture user's new password and send a request to save that new password.
Now I can create three different Rest APIs for above three steps and perform the task whatever required for that particular API.
If I am calling this forget password from a UI, in that case it will be responsibility of the UI client to take care of the sequence of the API's being get called to complete the whole process. But from API perspective user can skip the initial 2 API calls and directly call the 3rd API which save/overwrite the existing password with new password.
How can I enforce the sequence of steps(APIs) being called even if consumer of the API's is not a UI rather I am using it by some Rest browser client?
You should merge both second and third step.
Basically, we should receive the validation token with the new password request to confirm if it's a valid operation.
First step, the user request a "forgot password" operation and you send the token to his email/phone. You shouldn't send that information in the response of this request for security reasons.
Second step, the user introduce the token (or open an link with the token in the querystring, etc) and introduce the new password. The request that will go the API will contain both the token and the new password. If the token is valid for that user, you must update the password.
I want to create a Chat Messenger for my chat website (because of Push notifications).
But the user has to log in. I want to have it like the Facebook app, that at the beginning the username and password is requested and if the "remember" field is checked you don't have to login every time (maybe once a month then). What's the best way to do that? A session on the Server or saving username and password local? If I make a HTTP-Request where Session Data is saved, is it still available or active when I make a HTTP-Request on the same server later? (like for getting the chat content, or something else?)
I searched the internet, but didn't find something useful. If someone could tell me how to do that, or post a link or something that could help..
Thanks a lot!
The web server identifies a client through a token (e.g. session cookie). With each HTTP request, session cookie is sent to the server and server knows that request is coming from a client who has authenticated before.
The time span of this authentication is of course equal to the validity of the token (cookie in this case). The token can be invalidated on either client or server. You may require special mechanism for keeping sessions valid for month. Defaults are usually like half an hour.
Second option of storing password is more of a security decision. If you store user credentials, then you have to make sure that you do it in a secure manner.
If the user checks the save password field you could save the password to NSUserDefaults.
Although that's not good for encryption, it works. You should also use some type of encoding (SHA-1). You could make it aks for your password after say 10. To do that you would want a data store. You would load it into an int and then you can simply do something like runTime = runTime + 1; and if it get to ten purge the password data