If you’ve heard of Stytch already, you likely know how we feel about passwords. But we recognize that the journey to passwordless can be long and varied. And while we do hope one day to usher the world into a passwordless future, first and foremost we want to make it easy and safe for our customers to protect their users.
One of the easiest ways to reduce friction and improve user security is through password strength requirements. Unfortunately, to date these requirements have been poorly designed so that both users and security teams take on unnecessary stress and work.
In this article, we’ll go over the drawbacks of the de-facto legacy password strength method. Then, we’ll look at two specific tools developers can use today to protect their users, and the basics of how to set them up.
If you’ve created an account recently, chances are you saw something like what this user saw when trying to order a late night pizza:
The intention here is good. Allowing users to submit low-entropy passwords that can easily be cracked (such as “qwerty” or “abc123”) would expose both the application and user to risk of account takeover. To avoid this scenario, applications will often require users’ passwords meet certain characteristics to ensure the user sets a sufficiently secure password during account creation. As part of this step, the application will inform the user whether their chosen password is insufficient – and if so, it will often provide helpful suggestions on how to fix it (e.g. add a special symbol, a digit, etc.).
As we can see, though, the experience is…bad. Users who are trying to accomplish a simple, non-data-sensitive task, have to randomly insert a couple of exclamation marks or extra letters that they will likely forget as soon as the za arrives at their door. What happens the next time they want a late night pizza after a few beers with friends? Likely a labyrinthine password reset flow, in which they will add different random symbols just to get that midnight pie.
So how did we get here?
Typically, the legacy approach of password strength estimation follows the LUDS formula (lower case, upper case, digit, symbol). When implementing the LUDS method of password strength estimation, developers may think they are doing the right thing by checking to see if the password contains all of these characteristics. Unfortunately, humans are very predictable, and we often end up with insecure passwords that satisfy these conditions but are exceedingly easy for machines to crack. There are three main flaws in the LUDS approach:
While password managers may help with the last issue, adoption of these tools remains low. In short, though it’s a rather easy logic for engineers to set up on the backend, the LUDS approach to checking password strength is flawed, frustrating to use, and ineffective.
There is a better way to assess password strength that involves using a method known as “entropy.” Entropy is the measure of randomness in an information system. When applied to passwords, entropy is a measure of the length of the password and the randomness of the characters within the password. The higher the entropy, the higher the strength, because it becomes more difficult for someone to crack the password, even when using tactics like credential stuffing. Perhaps nothing explains password entropy better than this well-known XKCD comic:
As this comic shows so well, even though "Tr0ub4dor&3" looks like a strong password, it’s actually pretty easy to guess if you have some pretty simple resources most hackers have, ie., basic computing power, a database of common passwords, and knowledge of common character substitutions.
On the other hand, a password such as "correct horse battery staple" is much harder for computers to guess (and much easier for people to remember!). LUDS actually has a lower entropy score because it doesn’t factor in common human behaviors and patterns. LUDS assumes that all strings have equal entropy, and therefore password strength is viewed entirely as a function of the total search space. But because humans are rather predictable, this actually isn’t true. In theory it would take ~92 billion years to brute force a 16 character LUDS password, but modern password cracking approaches don’t just randomly brute force — they leverage common patterns of human behavior, which can cut that ~92 billion years crack time down to mere seconds for something like “P@ssword12345678.”
Rather than randomly swapping letters with symbols or numbers, entropy shows that length actually makes for pretty strong passwords (all other things being equal). You can confirm this yourself with something like rumkin.com's password strength checker. Even if the individual characters are all limited to [a-z], adding just one extra letter has an exponential effect on the password’s difficulty (and the time it would take a computer to guess it).
As a bonus, long strings of lowercase characters are also easier to type on smartphones and soft keyboards, making them even more user-friendly. If you don’t feel like doing logarithmic calculations every time your users (or you!) need to create a username and password, or you dread a potential future of 62-character passwords, don’t worry: you’re in luck! There are two great public tools that we highly recommend for helping generate strong passwords: zxcvbn and HaveIBeenPwned.
Developed in-house by Dropbox’s engineering team, zxcvbn provides a flexible strength assessment based on how resistant a password is to modern password guessing techniques. Named after the same keyboard area as “qwerty” (just two rows down), it’s designed to make picking a strong password easy for humans to generate and hard for robots to guess.
Zxcvbn works by first searching for matches to your user’s password in a list of common passwords, common names, common words, etc. If a match is found, it returns a score based on the match’s dictionary and pattern rank. If a match is not found, the library uses a set of rules to generate possible patterns, and it uses pattern recognition to score the submission. This includes things like repeating characters, sequential keyboard patterns, dates, common numbers, and so on. Because zxcvbn focuses on estimating the actual crack time of a given password, it’s a much more accurate assessment of strength than LUDS.
If you’re looking to improve password strength estimation in your application, or if you’re simply looking to get started with zxcvbn, there are many different ways to do it. The zxcvbn library is available in a variety of programming languages, including JavaScript, Python, Go, PHP, Ruby, and more (you can also use an API like Stytch, which incorporates the zxcvbn method into our Passwords product.)
Once zxcvbn-async is installed in your application, you can simply call into the zxcvbn function, passing in the password and an array of user input fields (e.g. username, email, etc.) that are being used in the application. The function will then return an object with a score attribute, which is a numeric representation of the password’s strength. This score will range between 0 and 4, with 0 being weakest and 4 benign strongest. While it’s most common to set the rejection level to < 1, some services like Stytch will reject anything < 3 for the sake of avoiding even moderately guessable passwords.
Zxcvbn is a major upgrade to the LUDS system for determining password strength, but it still doesn’t fully solve for the human tendency to reuse passwords across different applications. That’s where a tool like HaveIBeenPwned comes in handy.
HaveIBeenPwned offers both an individual-friendly website and a developer-targeted API that both monitor the web for stolen credentials in order to alert users and companies of those credentials’ insecurity. You can search for compromised emails, phone numbers, domains, passwords, and websites, and can even sign up for email notifications to notify you if one of your accounts has been compromised.
While you can use HaveIBeenPwned as an individual user, you can also integrate it into your product via their API, which checks whether a user’s email address or password has been exposed in a data breach. If it has, the API will return a list of the data breaches in which the user’s information was compromised.
To use the API, you would first need to sign up for a free API key. Once you have your key, you can then make a GET request to the API, passing in the user’s email address or password as a query parameter. If the user’s information has been compromised in a data breach, the API will return a list of the data breaches in which the user’s information was compromised.
At Stytch, we integrate directly with HaveIBeenPwned’s API, so that your users can also benefit from built-in breach detection in our Passwords product.
Just because passwords will one day be a thing of the past doesn’t mean they have to be such a pain in the present. Tools like zxcvbn and HaveIBeenPwned offer developers some lower-lift options that won’t make their users tear their hair out when trying to sign up.
If you’re interested in additional ways to eliminate friction from you signup or login, we’d always love to chat about how we can help simplify and streamline your auth flow.