Since this checks if they are authenticated using the hash/password and it's
async, we need to update authenticated to be async, which means we have to
update it everywhere it's used.
This changes adds a new method called `.canTry` to the rate limiter to check if
there are tokens remaining in the bucket.
It also adds suggestions from @oxy to make sure the user can brute force past
the rate limiter.
Before, we weren't checking if a login was successful before counting it
against the rate limiter.
With this change, we only count unsuccessful logins against the rate limiter.
We did this because this was a bug but also because it caused problems with our
e2e tests hitting the rate limit.