I am designing some Forgot Password functionality in an ASP.NET application, and had a question about the best way to secure the endpoint where a user can reset their password.
How I imagine this to work is (roughly) the following:
User clicks 'Forgot Password' on the login form
User is taken to a screen where they will enter their email associated with their account
User is then taken to a screen where they can answer some security questions (required by my company)
After answering questions correctly, the user will be sent an email containing a link.
User clicks the link in their email which will take them to a password reset form
My question here is, how can I ensure that when someone arrives at this password reset form that they arrived there from clicking on that email link, and didn't just manually type in the URL to get there?
One solution I've thought of was to encrypt some data and append it as a parameter in the URL inside the email. So when they click that link, I can decrypt the data and ensure it came from a valid email before serving the form. But I'm not sure the best way to go about this.
A solution consists of creating a token that can be used once on the reset page. You send by email a link similar to https://example.com/PasswordLost?token=467dc4ad9acf4, then the site checks that the token is valid and displays the password change page. To add more security it is possible to limit the validity of the token in time: about ten minutes are largely sufficient. Once in use, the token should no longer be usable.
There are many ways to generate the token. You can generate a random string and store it in a database with the associated email address and the expiration date of the token. Then, you can validate it by querying the database. The other solution that I prefer, is to generate a token that is ciphered by the server. Then, you can decipher it and validate the data it contains (user email and expiration date, last password changed date). This way you don't have to store anything on the server. This is what ASP.NET Core Identity does.
You can read my blog post about how to implement Password reset feature in a web application? for more information.
Related
I'm building a web application in asp.net C#, and what I'm doing is, if user tries to access his/her account with a wrong username and password for 5 times and attempts for 6th time,he/she gets redirected to a Captcha page, where he is asked to enter the captcha text. After the entry of captcha text, if it's true, I'm comparing the username and password passed from login page using usermanager.How can I do this, how to securely pass username and password from one page to another?
Update:
Only if the captcha is true, the 6th combination of username and password is validated.
I'm working on local host
Your workflow doesn't make much sense to me. If login failed 5 times and you ask for a Captcha, the username/password combination is still invalid, so I don't see why you need to carry that information around at all.
What you really want is to incorporate the Captcha on the login page and only require/show it when a few login attempts have failed from that session/ip/...
Also, the username/password gets encoded in clear text already in the form submission from the browser to the server. Therefore, if you want to protect that information, it's best to use SSL.
Things like user and pass should be encrypted if you want to pass them to other pages, so you should create a function to encrypt it and then you could pass them as session variable, or in the url for example.
You need to use SSL. After 5th failed login you send credentials back from server and store it e.g. in hidden form fields of captcha form. Than you send back POST request with credentials over SSL.
But basically you could just redirect user back to login after capcha was successful.
I'm building a sign-up / login flow for a web site. I plan to use Facebook as my identity provider instead of rolling my own.
I have a good feel for the server-side login flow with Facebook:
Call FB login API to get a code
Exchange the code for a user access token
Inspect the user access token
Validate the user access token details
After these steps, I'd like to check if the authenticated user is already registered in my system. If yes, simply return a newly generated bearer token, so the user can make subsequent requests to resource servers to access protected data.
If the user is not registered in the system, however, then I'd like to register them by creating a database entry. Before creating this entry though, I'd like to collect one piece of information from the user. Namely, I'd like for them to tell me their desired 'username'. I will use this unique username as my database primary key.
I'm not 100% sure on how to securely ask the user for their desired username before creating the database entry. This is my question. :)
One thought I had was to create a "redemption code". This code would be encrypted and contain the user initialization details, a secret only the server would know, and a timestamp. Something like this:
code: {
mySecret: "super-secret-value",
expirationDate: "date-value",
user: { ... },
}
After seeing the user is not in my system, I'd respond with the code + redirect the client to a page where they'd be able to specify their username. Upon submitting their username + code back up to the server, I could decrypt the code, and validate mySecret to determine the code is not tampered. If all is good, create the user in the database with the user information from the redeemed code. Lastly, I'd generate a new bearer token for the user and send it to the client.
Questions
Is my proposed redemption code strategy a secure way of requesting a username before creating the backend DB entry?
If not, what would be?
If yes, what is a secure encryption/decryption routine to use for this purpose in C#?
Flow Sequence
Steps 1-4 from above correspond to "Login" through "Validate" arrows.
My proposed redemption code strategy corresponds to the purple arrows.
Red text corresponds to Facebook specific nomenclature.
Note, Stack Overflow does something very similar to what I want to do. Before creating your account on SO, it will ask you for your desired Display Name (this happens after authenticating via Facebook, Google, etc.). After submitting your display name, your account is registered.
Use open source IdentityServer3.
Whatever flow you choose its already standardized in their server. Including (if you want or need) OpenID, OAuth2 etc.
I have setup a quick page to accept an email address which will send an email to it which will later contain a link to reset password or a new temporary one.
My project is a new ASP .Net MVC project using Identity. I thought the best way to reset it would be to send a link to the email which when clicked allows the user to enter a new one but then I'm not sure what to put on the page the link is directed to, to allow this functionality and keep the site secure.
Is it simply easiest in this case to send a new temporary one?
This was too long to fit in a comment so hopefully I don't get downvoted without actual code examples :O
A common solution that I've seen:
When a user requests a password reset, record a guid/random hash and expiration datetime to the user's information in your user store (db most likely).
An email with a link to a temporary page is sent to the user's email address on file (this solution does require a valid email address).
Once the temporary page is hit, the link can be set to immediately expire (set the expiration date to datetime.now, or remove the guid/hash from the user info, etc).
This temporary page URL would likely have the guid/hash for the recorded user in the query string, so it should be pretty hard to find without having the link in the email. For added security, the user can be required to put in the username/email that requested the password reset (as there should potentially be no mention of usernames/passwords on the page. Once this validation is done (or not) give the user the appropriate fields to reset their password.
Another final note on the "forgot password link" don't provide any information on whether or not a username "does not exist" as this can give the potential of finding valid user names on your site.
EDIT:
here's a previous stack overflow question that might explain it better than I did (don't look at the "accepted" answer, look at the most upvoted answer. :)
Generate temporary URL to reset password
You can find a complete sample that uses "Forgot password" functionality in the prerelease version of "Microsoft ASP.NET Identity Samples 2.1.0-alpha1" NuGet package.
Steps
Create Empty Web Application project
Install sample project: Install-Package Microsoft.AspNet.Identity.Samples -Pre
Start the application and register a new user.
Go to Log in page an click on "Forgot password". Then add the recent registered user e-mail.
Then, you will be able to debug the application checking the "Forgot password" process.
I want to add this feature to my application. It works OK but I'm afraid of a problem here. At first, I'll talk a little about how I implement the feature. Simply, the user has to register his email address first (at the registration time). If he loses his password, he can click on a link to activate the sender. This sender will send the password (corresponding to his username) to his registered email address. I think there should have many kinds of sender here and I'm using SmtpClient to send the email. This Smtp needs a NetworkCredential, and I provide it with some valid and active Credential. I have to create some user accounts (in Gmail and Yahoo networks), apply these accounts information as the credentials for my Smtp.
Here is the problem, my Password restoring feature won't work if all those credentials being invalid or inactive. I mean if all the user accounts (I created in Gmail and Yahoo mail) somehow are inactive, the Smtp will be unable to send the email. The most popular reason for those accounts being inactive is there hasn't been any access/login to them for a long time (e.g: about 3 months) It is almost certain that it will happen, except I have to remind myself to login to those accounts periodically to keep them active.
I wonder if there is any solution for this? I've thought of keeping those accounts information in a config file but the customer won't know how to edit that config file to change the sender credential information and even they know how to, that's so inconvenient. I've also thought of popping up a window requiring information for the sender credential from user (user may use his own email account or has to create a new one), it's also inconvenient, I think so. I've also think of logging to those accounts (via my application) periodically (about once a month) to keep them active. But I wonder if there is a better solution, plus that requires the user computer to be connected to Internet and this is not always met (even there is a situation that the user computer is always off line for months or years, but suddenly one day, he loses his password, he wants to get it back and at that time, he connects his computer to the Internet and uses the password restoring feature, but he can't because all the accounts built-in for the sender credentials has been inactive because of not having any access/login to them for months/years).
Do you have any idea on how to solve this problem?
UPDATE
I'm sorry to who suggested me that there is a security flaw here but I just want a solution for the password restoration. If you are kind enough please let me know what the security flaw is in detail. As I mentioned above, there is of course a security flaw because of the user password (a plain text) is saved in memory. But that's just a demo and it's only for demonstrative purpose for my real problem which is sending the user a new password (or any kind of authoritative access info). Here is what I want to explain more:
Suppose user's password is: Iloveprogramming
After hashed, it should be 3920bdbd4c000dd392e2501e89747173
That's all my application knows about user's access info.
When user typed in his password correctly, that entered password should be hashed into the same string above and this will be compared against the hashed string stored in the database and he should be logged in.
Now if he forgets his password, What can I do?
Here is the way most of websites do for us (who unfortunately forget our passwords):
- Support a link like "Forgot your password?"
- Clicking the link will lead you to a page like this:
-> Supply your user name: ............
-> Click OK (or any submit button) to get your new password.
I would like to do the same with my application. This is a windows forms application. I know that the content sent to the user email address should only be some confirmation link (about the password restoration), not a password (this is known only by the user who uses the email the password is sent to, however other users may disturb him by clicking on the 'Forgot password' link and fill in his user name). But it is only a must-do for a multi-user application, my application is in fact for only 1 user using on his own machine. What is the flaw?
Here is what I intend to do:
Auto-Generates the password, hashes this password and saves that hashed string into the database as the new hashed password for him. After that, send this auto-generated password immediately to his email address.
Dispose the string which stores the newly generated password.
What is the flaw here? And if it does exist, please let me know another solution for this? I'm just afraid of the email account which is used to send the password to my user's email address may not work (inactive) in future for some reason (as I said, not logging in for a long time).
Please feel free to explain the flaw detail in an answer, it may not answer to my original question but it does help me and I would accept that answer. Thank you!
Again, I don't have money for a dedicated website for the password restoring feature of my winforms application.
When the user check "remember me" i want to save the username and password.
The user should be able to login directly the next time.
What is the best way to do this?
I tried isolated storage but maybe the code i wrote is incorrect.
I hope someone can help me.
There is a great how-to on how to Encrypt Data in a Windows Phone Application - it may be worth comparing that code with yours
The best and secure way to do this.. Is storing unique ID which are relevant only to the servers that you are talking to as cookies.
Algo:
Get the username and password from the user
Check for authenticity of the user.
If authenticated, then generate an unique ID relevant to this user and store it on server.
Pass on this unique ID to client side and store this in a cookie. Set the max-age
Next time when the user come to your site. Check for the unique ID on the server and also check its age as well as when it was issued
If all's well , then give access to user