How to make a link expire after click - c#

Basically, I have an email service with a "forget password" functionality. There is a link being sent to the specified user that wants to reset their password.
What I want is to make that link expires after the user clicks on it (has been used).
I am using C#'s MVC, and webforms. I can't share the code for privacy purposes, unfortunately.
Any ideas?

I recommend using a stateful token.
What this means is you'll create a random guid (could be based on username, but still random).
Store that guid in a user/password linked table with the created date time and expiry time.
send the link with guid (http://emailsite.com/?token={random guid})
when the link is clicked, on page load, check the random guid param against the database.
if it doesn't exist, no password reset allowed. if it does exist and the current time is not > than expiry, allow password reset and delete the record. If it's to old, just tell them it's expired and delete the row.
instead of deleting the record, you can set it to inactive using a tinyint column.

Related

How to Properly Secure Forgot Password Endpoint

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.

ASP.Net MVC Identity Forgotten Password

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.

how can my application remember username and password after the user logs in?

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

Sending unique identifier by email

I am working on asp.net application.
I have to work on a functionality where system admin should be able to send invitations to view user specific documents by email. When user clicks on the invitation, system should be able to recognize the user and open the document.
I am thinking of using 16 digit hash keys against each email and store them in db when admin send the invitation. When user clicks the invitation retrieving the user details using 16 digit hash key.
But I feel there could be a better way of doing it.
Please suggest me to implement the functionality in a better way.
If your users generally have to log in, you may also want to force them to log in after clicking the link in the email before opening the document (or answer some other question), especially if the documents are at all sensitive in nature. At the very least you should disable the key after they open the document or after some amount of time has passed.
Email accounts get hacked all the time and you don't want the attacker to be able to click on the same link and gain access to any sensitive data.
In Database create a table that contains
UserDocuments { UserKey, DocumentKey, GUID, IsRead (false by default)}
store user and document key relation in this table.
Generate a random public key (GUID) and store this key in this table and send the same key to user using email, mail , phone or any direct secure way.
Let the document page contain DocumentKey in querystring.
When user opens the document page, authenticate user against the DocumentKey, UserKey in the table.
Don't allow if IsRead is false.
If authentication suceeds ask them to enter GUID.
again check in database if the userid is valid, if yes open the document and mark IsRead true.

How User account be locked for 30 min after 5 unsuccessful login attempts with asp.net?

I am using asp.net membership provider for managing users. I have a requirement to lock user accounts for 30 mins after 5 unsuccessful attempts. How should I do that using asp.net membership provider on the server side?
Also I want that 'Passwords should expire after 3 months', 'Last 10 used passwords should be remembered'. Is there any way to solve these requirements.
For the first requirement, the membership provider offers a MaxInvalidPasswordAttempts property which you can use in conjunction with the PasswordAttemptWindow property.
The 2nd requirement to the best of my knowledge would require you to customize the membership provider. The base membership provider does not retain prior passwords or have a forced password reset to my knowledge. This could be done if you create a custom provider yourself however.
Starter material for creating a custom membership provider
if you are using SqlMembershipProvider then use
maxInvalidPasswordAttempts for attempts
passwordAttemptWindow for locking for specified period
no option for password expiration or password history
but if you are using ActiveDirectoryMembershipProvider then use
maxInvalidPasswordAttempts for attempts
passwordAnswerAttemptLockoutDuration for locking for specified period
and ajust your domain policy for password expiration or password history
full info here
http://msdn.microsoft.com/en-us/library/ff648345.aspx#paght000022_usingthesqlmembershipprovider
ASp.Net membership provider doesn't provide any built in support for your requirements, still you can achieve them by doing some custom work.i-e
You can schedule a job that unlocks all locked user accounts, every 30 minutes.
In your application you can put a check if subsequent user logins are 3months apart, the user should be redirected to changepassword page.
Last 10 password of the user can be kept in another table, for which you need to write some code on change password functionality.
Create custom membership provider. There You can implement all needed functionality, see sample: http://msdn.microsoft.com/en-us/library/44w5aswa.aspx
you can do all the above mentioned functionalities by creating proper tables in database.
i.e.,
create one table to store count of wrong attempts, increment count when wrong attempt occurs based on the primary key i.e user name, within 5 attempts if he logs successfully then try to make that count to null
While locking the user after 5 unsuccessful attempts store the time and write one script to check that time continuously, when it meets 30mins call unlock method
For password also take day count, i.e., from changed date, each time when user logs in after checking user validity check for password day count if it cross 3days prompt them to change
If you are taking user name as primary key, create one more table to store max 10 passwords for each user, while inserting password to this table(when user changes his password),check the table for number rows for that user if it is 10 then based on the last lesser date you can delete that row and insert new password and you can compare new password with old passwords also while inserting

Categories

Resources