files/en-us/web/security/authentication/passwords/index.md
The original authentication method on the web, and still the most common, is the password.
In this guide we'll:
Finally, we'll discuss how even with the best practices, password-based authentication should be considered a relatively weak form of authentication, and should be supplemented with other methods or replaced entirely, if possible.
To provide password-based authentication, a website implements two main flows: registration and signing in.
When the user registers:
When the user signs in:
Looking at this overview, we can see some of the ways an attacker can impersonate the user.
Guessing
Credential stuffing
Interception
Database compromise
Phishing
Supporting password managers
: A password manager is an application that enables users to store passwords, so users don't have to remember them. Password managers may also autofill passwords in login forms, and generate strong passwords for users. Password managers are often implemented as browser extensions, and browsers also provide their own built-in password managers.
Password managers help reduce the threat of guessing and credential stuffing attacks, by making it much easier for users to have strong passwords and reducing the degree of password reuse. They also help counter phishing, because they will not autofill login details in the "lookalike" web pages used in phishing attacks, and this helps the user realize that the site is not legitimate.
In our guidelines for the registration and login flows, we outline how to ensure password managers will be able to work with your site.
Choosing strong passwords
Secure password transmission
Secure password storage
In the next three sections we'll take a more detailed look at the main flows needed for a password-based authentication system:
In each section, we'll highlight practices that help to minimize the threat posed by the attacks listed, but as we'll see, it is impossible to eliminate them completely.
In registration, a new user supplies a new username and password. The site is very likely to ask for an email address as well, and may choose to use the email address as the username.
The site should ask for this information using an HTML {{htmlelement("form")}}.
Well-designed forms help users work with passwords effectively, and also help password managers integrate with a site.
Typically, on a registration form, a password manager will:
Following the practices below helps password managers recognize forms they need to interact with, the elements they contain, and the points at which they need to be involved.
<form> element should be dedicated to registration.History.pushState() or History.replaceState().<input> elements should use the correct type:
"text" or "email" for usernames"password" for passwords.<input> elements should use the correct autocomplete attribute:
"username" for username"new-password" for creating a new password, in registration or password reset forms"current-password" for entering an existing password, in login or password reset formsFor more information, see:
The registration form typically asks the user to enter the password twice.
When the user submits the form, the website front end sends the username, both copies of the password, and the email address to the server, using an HTTP {{httpmethod("POST")}} request. This must take place over {{glossary("HTTPS")}}, to prevent attackers from intercepting the password in transit.
When the server receives the POST request, it validates the username and password. The username must not match an existing username, and the copies of the password must match each other.
The risk of guessing attacks can be reduced if users choose stronger passwords, and the policies websites follow can help with this.
When users choose new passwords, websites should:
Additionally, websites can:
Note, though, that this is far from a complete defense for these attacks: for example, data breaches may not be public, or may happen after the password was chosen.
Websites should also consider using a password strength tool like zxcvbn: note that this particular tool also checks passwords against the Have I Been Pwned data.
For more information, see:
The client may also validate data before sending it to the server, but this is only as a convenience to users: the server must still validate the data as well.
If any errors occur the server responds with an error message. Otherwise the server stores the password as a record in its database, keyed by the username.
Websites must not store passwords in {{glossary("plaintext")}} form. Instead, when the user registers with a new password (or changes their password), the password is hashed and the hash is stored. When the user presents their password on login, the site:
A hash is a one-way function, meaning that it's not possible to derive the original input to a hash function from its output.
This means that if an attacker gets access to the database, they will typically try to extract passwords by hashing lists of common passwords and comparing the results with the entries in the database. For this reason the hash functions chosen for password storage are intentionally slow and difficult to optimize.
Hash functions that are designed for hashing passwords typically allow you to configure the amount of work involved to create the hash, so they can be made slower or faster depending on the expected capabilities of the attacker.
Rather than calculate hash tables themselves, attackers can look up the password corresponding to a hash in a precomputed table (also known as a rainbow table) mapping possible passwords to their hashes:
| Password | Hash |
|---|---|
| pa55w0rd | 56965E2A... |
| abcdef | BEF57EC7... |
| letmein | 1C8BFE8F... |
Although these tables may be very large, such attacks can be effective because table lookup is a fast operation.
To defeat attacks that use precomputed hash tables, salt must be added to the password before it is hashed. Salt is a random value unique to each password. It does not have to be secret: salt is stored alongside the hashed password. However, it prevents an attacker from using precomputed hash values, because the salt means that a given password will hash to a different value.
As an additional defense, websites may also add pepper to the hash function's input. Unlike salt, pepper is:
Websites should use standard algorithms to hash passwords. These algorithms support all the features discussed above. The OWASP guide to password storage recommends, in order of preference:
Password storage and verification functions are difficult to implement securely, so you should use functions provided by a reputable framework, rather than trying to implement your own. For example, Django uses PBKDF2 by default but enables you to use a different algorithm if you choose.
If the website is intending to use email in the password reset flow, then the server must also check that the email address belongs to the user signing up. To do this, the server typically generates a random token and sets it as a parameter to a verification URL:
https://example.org/verify?<random-token>
The server then sends an email to the address the user gave. The email asks the user to click a link to the verification URL. The page can then extract that token and use it to find the user's record in the database. It can then mark the email address as verified.
To sign in, the user enters their username and password using an HTML <form> dedicated to sign-in.
Just like the registration form, the login form should be designed to work with (and be tested to work with) password managers. To do this, the form should follow the practices previously described in Form design.
When the user submits the form, the website front end sends the username and password to the server, using an HTTP POST request. Again, this must take place over TLS, to prevent attackers from intercepting the password in transit.
When the server receives the POST request, the server:
If the comparison succeeds, the server signs the user in and returns success.
If the record was not found or the comparison fails, the server must return the same error message in both cases. Otherwise, attackers can determine whether an account exists and can use this information to execute further attacks.
The password reset flow enables a user to reset the password, when they have forgotten or lost it. This usually relies on the user having supplied (and then verified) their email address when they registered.
When the user asks to reset their password, the website asks the user to enter their email address. The website may ask the user to solve a CAPTCHA at this point, to make it harder for a malicious third party to spam a legitimate user with multiple password reset requests.
The website back end then checks whether it has a record for this email address. Whether or not it does have a record, the website gives the same message to the user: that it has sent an email to the address given, with further instructions. Providing the same message in both cases prevents an attacker from finding out whether a given email address is associated with an account: this information could be used in further attacks (such as targeted phishing, or spearphishing, attacks).
If the website does not have a record, it sends an email to the address, telling the addressee that someone entered this email in a "password reset" form, but that the site did not have a record for this email address. This helps a legitimate account-holder who has multiple email addresses, and entered the wrong address in the password reset form.
If the website does have a record for this email, then the website:
https://example.org/reset?<reset-token>.When the user clicks the link, the reset page extracts the URL parameter and looks for a matching stored reset token. If a reset token is found and has not expired, the website allows the user to enter a new password. This flow follows similar rules to the registration form, to enable the new password to be recognized by a password manager.
Finally, the website emails the user confirmation that their password has been changed.
For more information, see:
The practices described above help reduce the risks of a password-based authentication system, but passwords remain an inherently vulnerable authentication method:
Although password managers and good password policies can help users choose strong passwords and not reuse passwords, they can't guarantee either outcome, leaving users vulnerable to credential stuffing and guessing attacks.
Even if users have strong passwords and do not reuse them, users remain vulnerable to phishing attacks.
To address these weaknesses, consider using alternative methods, either instead of passwords or as {{glossary("multi-factor authentication", "additional authentication factors")}}. For example, websites sometimes use passwords with a one-time password as a second factor, and some websites support passkeys, which are resistant to phishing attacks.