In the previous part, we’ve talked about the different ways that websites can use to identify the visiting user. But identification itself represents just a claim. When you identify yourself, you are claiming that you are someone. But there is no proof of that. Authentication, on the other hand, is showing proof that you are what you claim to be, like showing your personal ID or typing in your password.

More often than not, the websites need that proof to serve you sensitive resources.

HTTP has its own authentication mechanisms that allow the servers to issue challenges and get the proof they need. In this article, you are going to learn about what they are and how they work. We’re also going to cover the pros and cons of each one and find out if they are really good enough to use on their own (spoilers: they are not).

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

This is the fourth part of the HTTP Series.

In this article, you will learn more about:

Before venturing deeper into the concrete HTTP authentication mechanisms, let’s explore what the HTTP authentication is.

How Does the HTTP Authentication Work?

Authentication is a way to identify yourself to the Web server. You need to show proof that you have the right to access the requested resources. Usually, this is done by using a combination of username and password (key and secret) which the server validates and then decides if you can access the resource.

HTTP offers two authentication protocols:

  • Basic Authentication
  • Digest Authentication

Before learning more about each one, let’s go through some of the basic concepts.

Challenge/Response Authentication Framework

What does this mean?

It means that when someone sends a request, instead of responding to it immediately, the server sends a challenge. It challenges the user to provide proof of identity by entering the secret information (username and password).

After that, the request is repeated using the provided credentials, and if they are correct, the user gets the expected response. In case the credentials are wrong, the server can reissue the challenge or just send the error message.

Authentication Related request/response headers

The server issues the challenge by utilizing the WWW-Authenticate response header. It contains information about the protocol and the security realm.

After the client inputs the credentials, the request is sent again. This time with the Authorization header containing the algorithm and the username/password combination.

If the credentials are correct, the server returns the response and additional info in an optional Authentication-Info response header.

Security Realms

Security realms provide a way to associate different access rights to different resource groups on the server. These are called protection spaces.

What this means effectively is that depending on the resource you want to access, you might need to enter different credentials.

The server can have multiple realms. For example, one would be for website statistics information that only website admins can access. Another would be for website images that other users can access and upload images to.

/admin/statistics/financials.txt -> Realm=”Admin Statistics”

/images/img1.jpg -> Realm = “Images”

When you try to access the financials.txt the server will challenge you and the response would look like this:

HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm="Admin Statistics"

More about security realms: https://tools.ietf.org/html/rfc7235#section-2.2

Simple HTTP Authentication example

Now let’s connect the dots by looking at the simplest HTTP authentication example (Basic authentication, explained below):

1. User Agent -> Server

The user requests access to an image on the server.

GET /gallery/personal/images/image1.jpg HTTP/1.1
Host: www.somedomain.com

2. Server -> User Agent

The server sends the challenge to the user.

HTTP/1.1 401 Access Denied
WWW-Authenticate: Basic realm="gallery"

3. User Agent -> Server

The user identifies itself via form input.

GET /gallery/personal/images/image1.jpg HTTP/1.1
Authorization: Basic Zm9vOmJhcg==

4. Server -> User Agent

The server checks the credentials and sends the 200 OK status code and the image data.

HTTP/1.1 200 OK
Content-type: image/jpeg
...<image data>

Not that complicated, right?

Now let’s drill down and look into basic authentication.

Basic Authentication

The most prevalent and supported protocol out there. It has been around since HTTP/1.0 and every major client implements it.

The example above depicts how to authenticate by using Basic authentication. It’s rather simple to implement and use, but it has some security flaws.

Before going to the security issues, let’s see how the Basic authentication deals with username and password.

Basic authentication packs the username and password into one string and separates them using the colon (:). After that, it encodes them using the Base64 encoding. Despite what it looks like, the scrambled sequence of characters is not secure and you can decode it easily.

The purpose of the Base64 encoding is not to encrypt, but to make the username and password HTTP compatible. The main reason for that is that you can’t use international characters in HTTP headers.

GET /gallery/personal/images/image1.jpg HTTP/1.1
Authorization: Basic Zm9vOmJhcg==

The “Zm9vOmJhcg==” from this example is nothing more than the Base64 encoded “foo:bar” string.

So anyone listening to the requests can easily decode and use the credentials.

Even worse than that, encoding the username and password wouldn’t help. A malicious third party could still send the scrambled sequence to achieve the same effect.

There is also no protection against proxies or any other type of attack that changes the request body and leaves the request headers intact.

So, as you can see, Basic authentication is a less-than-perfect authentication mechanism.

Still, despite that, you can use it to prevent accidental access to protected resources, and it offers a degree of personalization.

To make it more secure and usable, Basic authentication can be implemented by using HTTPS over SSL which we talk about in part 5 of the series.

Some would argue it’s only as secure as your transport mechanism.

Digest Authentication

Digest authentication is a more secure and reliable alternative to simple but insecure Basic authentication.

So, how does it work?

Digest authentication uses MD5 cryptographic hashing combined with the usage of nonces. That way it hides the password information to prevent different kinds of malicious attacks.

This might sound a bit complicated, but it will get clearer when you see how it works on a simple example.

Example

1. User Agent -> Server

GET /dir/index.html HTTP/1.0
Host: localhost

The client sends an unauthenticated request.

2. Server -> User Agent

HTTP/1.0 401 Unauthorized
WWW-Authenticate: Digest realm="[email protected]",
                        qop="auth,auth-int",
                        nonce="cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ",
                        opaque="c29tZXJhbmRvbW9wYXF1ZXN0cmluZw"
Content-Type: text/html
Content-Length: 153

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Error</title>
  </head>
  <body>
    <h1>401 Unauthorized.</h1>
  </body>
</html>

The server challenges the client to authenticate using the Digest authentication and sends the required information to the client.

3. User Agent -> Server

GET /dir/index.html HTTP/1.0
Host: localhost
Authorization: Digest username="Gandalf",
                     realm="[email protected]",
                     nonce="cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ",
                     uri="/dir/index.html",
                     qop=auth,
                     nc=00000001,
                     cnonce="0a4f113b",
                     response="5a1c3bb349cf6986abf985257d968d86",
                     opaque="c29tZXJhbmRvbW9wYXF1ZXN0cmluZw"

The client calculates the response value and sends it together with username, realm, URI, nonce, opaque, qop, nc, and cnonce. A lot of stuff.

Detailed Explanation

Let’s define these:

  • nonce and opaque – the server-defined strings that the client returns upon receiving them
  • qop (quality of protection) – one or more of the predefined values (“auth” | “auth-int” | token). These values affect the computation of the digest.
  • cnonce – client nonce, must be generated if qop is set. It is used to avoid chosen plaintext attacks and to provide message integrity protection.
  • nc – nonce count, must be sent if qop is set.  This directive allows the server to detect request replays by maintaining its own copy of this count – if the same nc value appears twice, then the request is a replay.

The response attribute is calculated in the following way:

HA1 = MD5("Gandalf:[email protected]:Lord Of The Rings")
       = 681028410e804a5b60f69e894701d4b4

HA2 = MD5("GET:/dir/index.html")
       = 39aff3a2bab6126f332b942af96d3366

Response = MD5( "681028410e804a5b60f69e894701d4b4:
                 cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ:
                 00000001:0a4f113b:auth:
                 39aff3a2bab6126f332b942af96d3366" )
         = 5a1c3bb349cf6986abf985257d968d86

If you are interested in learning how to compute the response depending on qop, you can find it in RFC 2617.

4. Server -> User Agent

HTTP/1.0 200 OK
Content-Type: text/html
Content-Length: 2345
... <content data>

The server computes the hash on its own and compares the two. If they match it serves the client with the requested data.

Short Summary

As you can see the Digest authentication is more complicated to understand and implement.

It is also more secure than Basic authentication, but still vulnerable to a man-in-the-middle attack. RFC 2617 recommends that Digest authentication is used instead of Basic authentication since it remedies some of its weaknesses. It also doesn’t hide the fact that Digest authentication is still weak by modern cryptographic standards. Its strength largely depends on the implementation.

So in summary digest authentication:

  • Doesn’t send plain text passwords over the network
  • Prevents replay attacks
  • Guards against message tampering

Some of the weaknesses:

  • Vulnerability to the man-in-the-middle attack
  • Many of the security options are not required and thus make Digest authentication function in a less secure manner if not set
  • Prevents the use of strong password hashing algorithms when storing passwords

Due to these facts, the Digest authentication still hasn’t gained major traction. The Basic authentication is much simpler and combined with SSL still more secure than the Digest authentication.

Conclusion

That’s it for this part of the HTTP series.

We’ve gone through different authentication mechanisms that HTTP offers by default and talked about their advantages and disadvantages.

These concepts are hopefully not just the letters on the screen anymore, and the next time you hear about them you will know precisely what they are and when to apply them.

You are also aware that there are security risks that haven’t been solved by these authentication mechanisms. That’s why concepts like HTTPS and SSL/TLS exist. We talk more about security risks and how to solve them in the next part of the series.

If you found some of the concepts in this part unclear, refer to part 1, part 2, and part 3 of the HTTP series.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!