We differentiate between password change and password reset. Password change is when the user enters both current and new passwords to update the password for an account. Password reset is when the user has forgotten the current password for the account and needs to establish a new password.
CI providers should avoid re-implementing the password reset workflow if possible. Using external identity providers (e.g., InCommon and/or Google) avoids the risks of managing passwords directly, enables users to log in via an account that they use regularly (so users are less likely to forget the password), benefits from available security features such as two factor authentication, and leverages the password recovery support of the external identity provider(s). Alternatively, CI providers could use an existing password reset workflow built-in to their web application framework (e.g., Joomla or Laravel) or identity management (IDM) platform.
However, in our experience CI providers still sometimes find the need to implement password reset in their unique environment. In this article, we provide an example email-based password reset workflow and discuss design choices and risks that CI providers should consider when implementing password reset. The workflow assumes that users have previously registered a contact email address that can be used for password resets.
Password Reset WorkflowThe goal of the following workflow is to allow a registered user to reset their password without requiring assistance from support staff.
- On the "Sign In" page, the user clicks the "Forgot Password?" link.
- The user is prompted to enter their username or registered email address.
- The user is prompted to "check your email for a password reset code to enter below".
- The user enters the password reset code on the web form.
- The user enters their newly chosen password.
- The user can now sign in with the newly chosen password.
Behind the ScenesTo implement this workflow, the web application performs the following actions behind the scenes:
When the user enters a username or email address (step #2), the web application checks for a match with a valid user account. As with any input provided by the user, the web application sanitizes the username and email address values before querying back-end databases, to protect against injection attacks. In response to the user's submission, the web application does not indicate whether a match was found, to avoid disclosing the existence of registered accounts to unauthenticated users. Instead, whether a match was found or not, the web application displays, "Please check your email for a password reset code to enter below. If you do not receive an email message, please contact the help desk" (step #3). If the username or email address provided by the user does not match a valid account, no further action is taken.
If the web application finds a valid account matching the user's input, the next step is to generate the password reset code (for example, an 8 digit random number), store a salted hash of the reset code (for example, using bcrypt) with a timestamp and the user's account ID, and send the email message to the user's registered email address. The password reset code is a time-limited, one-time-use random "nonce" value to confirm that the user received the message at the registered email address. The web application removes stored reset code entries immediately after use or after the time limit (for example, 15 minutes) has elapsed.
Next, the user enters the password reset code from the email message on the web form (step #4). The web application hashes the entered reset code and searches for a match among the current stored values. If no match is found, the application displays an error and prompts the user to try again (for example, allowing up to 3 tries before aborting the process). If a match is found, the application prompts the user to enter a new password (twice for confirmation) (step #5) and checks that the new password is sufficiently strong. If it is, the application changes the user's password to the new value, removes the stored reset code entry, and sends a confirmation email to the user's registered email address. The user can now return to the standard "Sign In" page and proceed to log in with the new password (step #6).
Password Reset Email MessagesThe above workflow sends two email messages to the user's registered email address: 1) the message containing the password reset code and 2) the message notifying the user that the password reset completed successfully. These messages should follow recommended practices for email communications, including a trustworthy From address (in the correct DNS domain) and no HTML content. The messages should also include instructions for contacting the help desk if the user did not initiate the password reset. The user's password should never be sent in email messages.
Logging and MonitoringThe password reset capability can be a target for attacks and a source of user support issues, so it is especially important to log all system activities related to password resets and monitor for unexpected behavior. Log messages should have accurate timestamps and should include the originating IP address for password reset requests.
RisksThe primary risk for the password reset process is the possibility that an attacker could reset a valid user's password and thereby obtain unauthorized access. Potential attack vectors include:
- Disclosure of reset code via email: Since the password reset code is sent over unsecured email, it could potentially be disclosed via email account compromise or network eavesdropping, allowing an attacker to use the code to change the user's password. Enforcing a short lifetime on the reset code limits the window of vulnerability against this attack.
- Network disclosure of passwords: The web application should follow HTTPS best practices to protect passwords against active and passive man-in-the-middle and phishing attacks.
- Exposure of reset code database: Storing reset codes in hashed (salted) form in the web application protects against disclosure of valid reset codes due to inadvertent disclosure of the reset code database.
- Brute force attacks on reset codes: Generating long, random reset codes, valid for only a short time, makes it infeasible for an attacker to successfully guess a reset code through brute force. Aborting the reset process after 3 failed reset code entries also protects against guessing attacks. However, beware making reset codes so long that they are inconvenient for users to input. (8 random digits is a reasonable length.)
- Compromise of the password reset front-end web application: In a system architecture with a back-end authentication system (LDAP, Kerberos, etc.) that may be shared across multiple front-end systems, enabling a front-end web application to reset passwords introduces the risk that an attacker who compromises the web application could reset many user passwords and gain further unauthorized access. Unlike password change (which requires knowledge of a current valid password prior to making password updates), password reset trusts the web application to update passwords without further validation by the back-end authentication system. Isolating the password reset functionality to a dedicated, well-secured front-end system can help to mitigate this risk, as well as logging and monitoring on the back-end system.
ExamplesThe "Forgot Password?" links on the XSEDE User Portal and on HUBzero provide illustrative examples of self service password reset functionality similar to what is described above.
Self Service and Exceptional CasesIf all goes well with the above workflow, the user is able to reset their password without assistance from help desk staff, hence "self service". However, the user may still need assistance if (for example) they lose access to a previously registered email address and therefore can not complete the self service workflow. It is important to have documented processes for handling these exceptional cases at the help desk without introducing new risks for social engineering attacks. A phone call from the help desk to a previously registered phone number can help re-establish account ownership. However, when in doubt as to the identity of the account holder, it may be better to ask the user to create a new account rather than risk improperly resetting the password on an existing account.
What do you think about self service password reset? Post your comments below.
For more about how CTSC helps NSF projects visit http://trustedci.org/howwehelp.