Securely Handling User's Login Credentials
For most websites, you have different areas within it (home page, user profile, admin page, etc.), some of which will be public and others will need to be restricted to only certain users. You often want to uniquely identify users so you can provide customized content or to capture specific information from a user. Many sites also need to protect part of the site, such as an administrative area to maintain and update the content of the site. In a CMS site, some users may be able to create content, but others must approve that content before it is shown to the public.
Securing the Username and Password
Whatever the need, restriction or customization requires identifying each user accessing your site. For an Internet facing site meant for general users, the username and password still prevails largely because there isn't a better option. There are other options if you're working in special environments, such as a company Intranet, where you have some control over the site visitors.
While a common need, logins and passwords are often handled in a way that leaves the website and its users, unnecessarily more vulnerable to security attacks. By following some best practices, you can better protect your site and its contents from hackers. The consequences of poor protection can be serious. Imagine a site where any user could post content that appeared to be from the company due to poor password management or an online store where any user could view all orders placed on the site.
Let's take a look at a few security considerations while working with logins and passwords on your websites.
Usernames: Emails or Generic
The login consists of a username which identifies you, and a password validating you are the user that you claim to be. Websites often allow the user to either specify a custom username or use the user's email address as their username.
Emails don't change often and most websites already gather this information, so the user will also be less likely to forget their email than a username they created. The email will also automatically be unique as users rarely share an email account and those who do, likely wouldn't want separate accounts.
The downsides to an email include that two people who share an email, cannot have separate accounts. Additionally, if your site has a legitimate reason for one person to have multiple accounts, this may not be possible with emails, but easier to implement using usernames. It's also likely an email is easier to hack since a user likely uses the same email at every site, but the majority of usernames will likely not be much more difficult to hack, as users tend to reuse usernames just as much as they reuse passwords.
Unless you have a specific reason to avoid an email address, prefer the email for the login username. The use of the email has also become the norm on websites. Don't forget though, to provide an email-based-login with a way to change the email. Without this feature, a user would need to create a new account and lose all past history just because they changed Internet providers or lost a previous account due to graduation or changing jobs, causing their old email to go away.
Always be careful while using email as the login to not show it publicly, for both privacy reasons and spam prevention issues.
Logins Can Provide Too Much Info
The login page of your website will be the first point of research for a hacker. The hacker will attempt to determine valid accounts that exist on a website. Properly handling the login page will make the hacker's job more difficult. To start, you should minimize the amount of data a failed login provides to an attacker. Your initial thought when someone enters a username that's not recognized might be to provide a helpful message that they should check their username. You can provide a more secure page by showing the same error message when the username is not found and when the password doesn't match the password for the given user. The message should indicate that the combination of username and password was not correct, to let the user know to verify both pieces of information, not just one or the other.
If your site uses emails for the login username, an attacker can easily validate if a user has an account on your service if you return a different message for an unknown login compared to a failed username and password combination. It does make things a bit less convenient for the user, but the added security is normally the better trade off.
As noted, taking away the specific message for an invalid username, trades increased security for a worse user experience. Providing a message that a login does not exist will help the user notice typos such as typing
john instead of
jon easier. That message also helps a user that does not remember which username they used on your site. Do keep in mind that these types of messages give hackers a simple and easy way to verify if a user exists on your site.
You can also help foil a hacker by better handling multiple login attempts. Accidentally mistyping a username or password more than once occurs fairly commonly from a mistyped character, transposing two characters, or using the password for another site instead of the correct password. Allowing unlimited login attempts opens the door to a brute force attack of trying usernames and passwords repeatedly to determine the correct login. Automated tools and scripts speed up the process allowing a hacker to methodically work through many potential passwords, until finding the correct login.
Introducing an increasing delay time after each failed login attempt also helps foil hackers. The first login attempt happens normally. The second login is delayed a fraction of a second before returning the result. Further attempts are delayed increasingly longer before returning a response. This delay allows for minimal disruption for a legitimate user that's made a mistake, but slows down the hacker attempting to brute force the site.
For more sensitive data, a stronger approach can be taken by locking out the account after a number of failed attempts. Locking the account disables it either temporarily or permanently. The lockout stops brute force attacks as after a point, the login will not work. A temporary-disabling should have minimal affect on the user as long as a message for the reason for the lock out is displayed. A permanent lock requires the user to contact support to fix the problem and better fits logins, protecting important data.
Passwords are the most sensitive aspect of the login. Never store passwords in plain text. Never. Ever. Doing so means almost any security problem can expose login information. Even encrypted passwords should be avoided as if the hacker gains access to the encrypted data the decryption process can be much easier. Any storage where you can retrieve a password, makes it easier for a hacker to do the same.
Salting and Hashing
Passwords should be stored salted and hashed. A salt is a randomly generated, unique value stored for each login and added before hashing. Adding the salt prevents identical passwords from having the same hash and prevents a hacker from building a list of the hash result of possible password combinations in advance. By adding the random hash, a password of
abc123 (please never use anything like that as an actual password) will result in a different hash for every user.
A hash function turns the password into a fixed length value. There are functions specifically designed for passwords such as PBKDF2 or Bcrypt. The GPU processors in modern graphics cards can perform the computations needed to hash and can break many weak algorithms quickly. Dedicated machines for the purpose of breaking passwords can determine any eight character password or less, in under six hours.
Users often tend to reuse the same password for most sites where they have accounts. Many sites have begun testing the exposed credentials from major account login hacks against their own logins and contacting users whose username and password combinations match. Evernote and Facebook recently examined login credentials released from Adobe and alerted users using those same credentials.
The easiest way to handle passwords correctly is to use the tools included in your web framework. Password security is complicated and getting just one thing wrong can leave your user's passwords open to attack. pH pass provides a public domain library for PHP using Bcrypt. The older built in .NET membership providers used weaker hashes, but the new Universal Providers use PBKDF2. Rails also provides a Bcrypt gem.
When you properly secure passwords so that they cannot be retrieved, you lose the ability to provide the user a forgotten password. Then, you need to provide an alternative way for a user who legitimately forgot their password to reset the password in a secure manner.
The Password Reset Page
A good reset-password page allows the user to change the password without knowing the current password. The traditional method allows the user to enter their email address and then sends a link to a webpage that allows them to reset the password. Sending a link is more secure than sending a password since the new password isn't created until the user accesses the page. Sending a new password by email would create a new credential that anyone intercepting the email would be able to use without the user's knowledge. If someone intercepts the email and resets the password, the user will know when they access and attempt to reset their password.
A good reset page should also not provide validation that an account exists. The logic is the same that we discussed in regards to not providing feedback if an account didn't exist when logging in. Even if the login does not exist in the system. The best approach is to provide a message that instructions have been sent to the email address on file. You should still send an email to the entered email since it could be a legitimate case of having forgotten which email was used for an account, such as entering a work email instead of a personal email.
Password Reset Links
The link to reset passwords should be designed so the reset request has a limited lifespan and can be only used one time. Create a unique token for each reset request, tied to the account requested and store it in a database. This token becomes part of the URL emailed to reset the password. The token also should be assigned an expiration time and be removed after the reset completes. If someone attempts to use a token that has been already used or expired, the request would fail. The expiration time needs to be long enough to allow the email to be received and the user to complete the action, but not so long as to allow use too far in the future. A time frame of a few hours usually will suffice.
Resetting a Password Via Email
Resetting a password using email also makes the security of your site dependent on the integrity of the user's email. If the email can be accessed, then that person can reset the password. Sites can add security questions that must be answered before resetting the password. Security questions provide little extra security if the answers are easy to find. A security question of "What is my hometown?" provides little security if the answer can be found on the person's Facebook profile. For more on developing good questions, see http://goodsecurityquestions.com/.
Two Step Authentication
A login and password requires only one pair of information to access a website. When that information is provided, then the user is assumed to be the correct person. To make stealing credentials less effective, you can add a second step to the authentication process. In addition to something that the user knows (the username and password), the user also must use something they have in their current possession, commonly a cell phone through either SMS or an application for this purpose.
Banks were probably the first to implement this process using custom hardware to generate a time dependent code. Google popularized the use of SMS text messages or an app as a second step. Many sites now use a login compatible with Google's implementation of RFC 6238. You can find libraries already implementing this technique for most popular frameworks such as ASP.NET, ASP.NET #2, Ruby on Rails, PHP, and Django.
To avoid these problems you have another option, let someone else deal with all this by integrating with a third party for authentication such as Twitter, Facebook or OpenID. Doing so offers benefits and disadvantages. It does take away most of the security concerns that we've discuss here as someone else deals with those issues. However, these other sites are also probably a bigger hacker target than you. If you use another site to handle authentication, then if that login is compromised, the hackers have access to your site.
Using a known third party can both help and hurt from a reputation and social point of view. The advantage of allowing login with either Facebook or Twitter is that so many users already have accounts there that they would be happy to use it. Other visitors may view the integration with these sites as a negative feature and not use your site because of it or if it is the only option provided to them.
Your web application's login plays a vital role in securing your site. Taking care to protect your login will do much to protect your site, your site's users and their private information. To work securely with logins, minimize the amount of data your login and password reset pages could potentially provide to a hacker. Also, put security measures in place to make it more difficult to guess your user's passwords via brute force.
Protecting passwords is a critical concern of any site. Poorly protected passwords make the hacker's job easier and can end with the login credentials of your site exposed to the public. Using hashed and salted passwords makes the hacker's job much more difficult. Additionally, adding the option of a second step to the login process can provide more protection for your site's users. You can also chose to utilize a third party to handle logins to your site.