2

I am trying to decide which work factor to use for our hashed passwords, and I am facing the following dilemma. Let me elaborate for a moment.

Basic HTTP authentication works as follows:

  • The user tries to access a protected resource.
  • The web server returns HTTP error code 401.
  • The web browser asks the user to enter credentials.
  • From now on, for each web request:
    • the web browser includes an Authorization header containing the user name and the password (in clear text, which is why this authentication scheme should only be used with HTTPS), and
    • the web server validates the user name and the password.

As you can see, the final bullet point is executed for each web request. Thus, if I set the work factor to a level that causes password validation to take, for example, 1 second, I don't just have a 1 second delay when the user logs in (which would be OK) - I have a 1 second delay for every single HTTP request the logged-in user makes (which is not OK and would slow down a responsive AJAX web application to a crawl).

I'm also the one writing the web server authentication code, and I can think of a few ways to work around this issue: For example, after each successful authentication, I could cache the user name and a weakly hashed (fast) version of the password in memory and first try to authenticate against those credentials in future requests.

However, I don't want to get creative when it comes to security (following the Don't Roll Your Own Crypto principle). In addition, Basic HTTP authentication has been around for ages, and the recommendation for strongly hashed passwords has been around of ages, so this should be a "solved problem", right? In that case, what is the time-tested, canonical solution for this issue?

2
  • 5
    "... what is the time-tested, canonical solution for this issue" - Not to use Basic Authentication in the first place. It has more problems in addition to what you mention, like no way to log out and no support for MFA. It also does not support the usability expected today. Commented Apr 20, 2022 at 15:25
  • Steffen is exactly right. I see the appeal, because Basic Auth is so universal and so battle-hardened. But any Basic Auth incremental improvement effort is just "doomed to recreate" a modern authentication method. Better to just jump to the endgame and move to a modern one. In the meantime, pick the strongest work factor that the user experience can tolerate, and minimize the number of requests where you can. Commented Apr 20, 2022 at 18:34

2 Answers 2

2

Basic authentication for websites is relatively uncommon. Most websites use a single login page and issue a session cookie that allows users to access the site until it expires or they log out. This typically provides a better experience for the user, who can be reminded what the username is (is it a regular username or an email?) and what restrictions, if any, are allowed in the password, as well as information about a forgotten password or a 2FA prompt. That is all much more difficult or impossible with plain Basic authentication. In addition, Basic authentication makes it hard to sign out.

It is still common to see Basic authentication in various APIs, where a user may have a username and a token, and this is no more or less secure than using a token via a Bearer scheme. Usually such tokens are pseudorandomly generated with sufficient entropy and so can be stored securely with a simple unsalted hash or HMAC, or they are created with an HMAC or digital signature and therefore can be verified without storing them.

My recommendation for a website is to implement a standard login page without using Basic authentication. Most secure session libraries (which are available for all major languages) will either persist just a pseudorandomly generated identifier in the cookie or will implement a secure encrypt-then-MAC or AEAD scheme for the data in the cookie. Therefore, all you need to do is use a reputable session handling library in your language of choice and things should be relatively easy.

1
  • +1. As Steffen's comment says, the solution is "just don't ever use basic auth for anything with user-memorized passwords". Sessions - either using random opaque blobs or JWTs for the session token, and passing it in a cookie or a header (usually Authorization but as a "bearer token") - are better in many ways than basic (or digest) auth.
    – CBHacking
    Commented Apr 21, 2022 at 8:12
0

If you are restricted to the Basic authentication (it pretty much happens), a viable strategy is to cache the authentication state over the duration of the TCP/TLS connection. Of course, you have to use persistent connections as well.

Alternatively, you can cache a weaker and faster password hash in RAM (it will not be stored permanently so it will require a memory disclosure first in order to be attacked by bruteforce and if you get a memory disclosure breach chances are the attacker will get the plaintext password anyway).

Another strategy is to Basic authenticate only a specific URL (not the whole webapp) and use it to set a session cookie for the subsequent requests.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .