Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
334 views
in Technique[技术] by (71.8m points)

php - How can I provide password reset functionality in a secure way?

I'm currently finishing up a website where users are required to create a personal account in order to play a game that is hosted on the same website. What I'm currently having difficulty figuring out is how to implement secure password reset functionality for the users in the case of a forgotten password.

This is the process that is currently in place:

Step 1: User clicks on "Forgot Password" link on the website.
Step 2: User is brought to form and enters email address twice before being sent email.
Step 3: Email contains link to another form where the user can enter a new password twice for confirmation. Upon entering the second form, the system inserts a new record into my Recover_Password table in a database which contains the columns "id", "token", "created_at", and "expires_at".

This is the link -> (mywebsitename).com/form?id=99999&token=
Where "id" is the user's id and "token" is generated from do_hash($id . date('Y-m-d'))

Step 4: User completes form and is brought to the login page. The system clears the token record from the database and updates the user's current password from the user table.

Also I want to know what to do if the user tries refreshing the browser page when they are at the second form. I am currently only allowing access to the page if there is an id and a token value in the get parameters and that they both exist in the database.

I am using Codeigniter for the entire website and need to kow if this is a secure way of doing this and also how I should handle the token and the database. Thank you!!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

A secure way to handle password-resets could look like this:


Password reset request:

  1. User opens password-reset request form and enters the email address (no need to enter it twice, just make a syntax validation).

  2. Your application checks whether the email exists in your database. If it exists it creates a token, which should be random and not derrived from informations like userid or timestamp. A hash of the token will be stored in the database in a separate table, together with the userid and an expiry date. A link with the token is sent to the user per email.

  3. The application shows a confirmation that the email was sent. This page can contain the email address, so the user can check if he had a typo (after all there was no information whether the email was in the database, so that an attacker cannot test its existence).

Password reset:

  1. User clicks the link and opens the reset form. On this form he can enter the new password twice. The token has to be included as hidden input tag in the form.

  2. After submitting the form, the application checks he token. If it matches and has not expired, the password can be changed and the user can be logged in directly (you can spare him the login form then). At last the token should be deactivated, i myself prefer to keep the entry, so i can inform the user that the token was already used, when he clicks the link again.

One problem you will encounter is, that you have to find the hash of the token in the database. There are two possible ways to store the token:

  • You hash the token with a hash algorithm like SHA512 without a salt. This is secure if the token is very strong (minimum length 20 with 0-9 a-z A-Z). Theoretically you have to check whether such a hash already exists before you enter it in the database, in practise this is negligible. I implemented a password-reset class that can handle such tokens.

  • You hash the token with BCrypt and salt. This allows for shorter tokens, but you cannot search for the hashed token in the database. Instead you have to include a row-id in the link to find the token.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...