A browser or curl asks a server for a protected page, one HTTP message at a time — see every header of the challenge and the credentials, set the users and passwords on both sides, change them mid-way, and turn on a session cookie to see what the server starts keeping.
HTTP keeps nothing between requests, so a server that wants to know who is asking must be told on every
request. Basic authentication, defined in
RFC 7617
, does it
the simplest way: every request carries the username and password in a header. The simulator shows
each message whole, so you can read the password crossing the wire, and each side's settings can be
changed to see what the other one does with it.
The simulator's layout
- The client on the left is a browser window or a curl command line. The browser asks for a page
from its address bar and shows the body of the answer; on a 401 it opens its sign-in dialog over the
page, which blocks the tab until you sign in or cancel. curl takes the username and password in
-u.
Both keep what a real one keeps: the credentials it remembers and the cookies it was given. - The server on the right holds the realm, the users and their passwords. Send the response
answers the request on the wire, and names the status it will send; below, the server shows the checks
it ran on the last request, one line per check.
- The wire in the middle shows the message of the current step, every line of it. Clicking a line
says what it does; the line the step is about opens by itself.
- Step and Prev move one message at a time, so Step also sends the server's response. The server
answers by its settings, so its response is always the next step after a request.
- Messages so far, under the simulator, is the exchange as a sequence diagram. A dot on a line is a
change of settings; clicking a row goes back to that step.
Changing a setting while stepped back into the past discards the steps after that point.
The challenge and the credentials
A browser sends no credentials until a server asks for them, so the first request for a protected page
costs a round trip:
- The first request carries nothing, and the server answers
401 Unauthorized with
WWW-Authenticate: Basic realm="course". That header is the challenge: it names the scheme and the
realm, the name of the protected area. A browser files the password it remembers under the site and
the realm, but leaves the realm out of its sign-in dialog, because a site could write anything there. - The header alone asks for the login. The 401's body holds no code: the browser shows it only if the
reader cancels the dialog, as Cancel shows. A site that logs in with a form works the other way:
the body carries the HTML form, and there is no
WWW-Authenticate header at all. - The second request carries
Authorization: Basic, followed by the username and password joined
with a colon and base64-encoded. - The server decodes the header, splits it at the first colon (a username may not contain one), and
compares the password with the one it holds.
curl with -u skips the challenge: it builds the header before the first request. Switch the client to
curl -u to see it.
base64 is an encoding
YWxpY2U6c2VjcmV0MTIz is alice:secret123 written in a 64-character alphabet, so that any byte
survives inside a header. Reversing it takes no key, which is why the simulator can show the decoded
value under every Authorization line. Over plain http:// every machine on the path can do the same;
Basic authentication is acceptable only inside TLS.
What each side keeps between requests
- The server keeps nothing. It checks the password on every request, from the start, and keeps no
count of failures.
- The browser keeps the password. After a successful sign-in it adds the same header to every later
request to the site (
RFC 7617, section 2.2
),
so the password crosses the wire again and again. Forget drops it, which is what closing the
browser does and the only way to log out.
- A password changed on the server reaches no client. The browser keeps sending the old one and gets
a 401, then shows its dialog again.
The examples The password changes on the server and A wrong password and an unknown user play this
through.
A session cookie: the server starts keeping state
Turning on Set a session cookie after a correct password makes the server do something Basic
authentication does not include:
- After a correct password it creates a random session id, records which user it belongs to, and
sends it in
Set-Cookie. - The browser returns the id in a
Cookie header on every request, and the server accepts it in place
of the password: forget the password in the browser, and the requests still succeed. - Revoking the session on the server makes the cookie worthless at once. This is a logout, which
Basic authentication alone cannot do.
The price is state on the server: a session table it must keep, share between its instances and expire.
The example A session cookie (not part of Basic) plays this through.
Simplifications in the simulator
- Every path on the server is protected by the one realm.
- The server shows passwords in plain text so you can edit them; a real one stores a hash, and hashes what
arrives to compare.
- The connection, TLS and the TCP beneath it are not shown: every step is one HTTP message.
- Sessions never expire, and the cookie carries only
Path and HttpOnly.
The course
Authentication and Secrets
builds the same exchange
with nginx and curl in its chapter HTTP is stateless.