I just logged into Grubhub and I realized they have one of those two stage login systems. It's split into two parts where you enter your username on it's own, then it redirects you to screen that tells you "Welcome back!" and prompts you for your password.
Not good!
The problem with this approach is that I could create a script to spam that API and find out who has an account with them. Imagine you had your data leaked from one of the many recent hacks. They will have access to your email address and can spam a bunch of services that use that two stage login API. Now they potentially have more accounts related to you where they can attempt to attack.
In some cases it's can be even worse. What if it was the ole Ashley Madison that allowed for this? The attacker could try to blackmail you. Some services reveal a lot about a person, just by knowing they have an account there. For those unfamiliar, Ashley Madison was a site to find people to cheat on your spouse with. Wouldn't be great if people found out. In fact, a hack did take that company offline and caused problems for a lot of people. If I remember right there were even .gov emails that were used, so you could find if your favorite politician is a cheater or want to be cheater.
Also not good!
Sometimes even a login system that does work in one step can also leak the same information. Sometimes people check the database first to see if a user exists and returns an error code if they aren't found. It might be labeled as "invalid login", but it should return more quickly than if the user does exist. When a user is found in those cases, the code would likely be retrieving a hashed version of the password, hashing the one sent, and compare the two. If they don't match then you also get an "invalid login" response. Modern cryptography is purposely computationally expensive to perform -- it protects against brute forcing attacks. So this means it's not a trivial amount of time to make that comparison of the two hashed passwords.
Also also not good!
I thought this was a solved problem in 2025, but here we are! The good news is there's an easy way to prevent the leaking of user data. First, your login method should take both a username and password; don't break it into two steps. The second is to always do the hash and comparison. Technically the hashing is what will take most time, but even the comparison might return more quickly when no user is found, since we are comparing the hash to null, so it's not a bad idea to also have something to compare it to, to consume the same CPU time (as if we did find the user). This should all ensure no data is leaked because we aren't telling the consumer of the API with an explicit response nor are we telling them when the call returns more quickly. Happy hacking!