skip to content

questions

5

Walk me through exactly what a client puts in the HTTP Authorization header when using Basic authentication, and what protection that encoding gives you.

level: juniorimportance: must knowfreq 72%

answer

  1. base64(userid ':' password)
  2. encoding, not encryption — one-step decode
  3. split on FIRST colon; user id has no colon
  4. stateless: header on every request
  5. TLS mandatory; scrub Authorization from logs

basics

~20 s

The client sends Authorization: Basic <base64 of userid:password>, recomputed on every request. Base64 is reversible encoding, not encryption or hashing — anyone who captures the header decodes the password instantly, so only TLS provides confidentiality.

solid answer

~50 s

Basic joins the user id and password with a single colon, encodes those bytes with base64, and sends them as `Authorization: Basic YWxpY2U6czNjcmV0`. The user id must not contain a colon; the server splits on the **first** colon, so the password may contain one. Base64 is a transport encoding — it exists so arbitrary bytes survive an HTTP header, not to hide anything. `base64 -d` recovers the password in one step, so Basic is only acceptable inside TLS. Basic is stateless: there is no session, so the client attaches the same header to every request, and the server re-verifies the password every time. A server advertises Basic with `WWW-Authenticate: Basic realm="...", charset="UTF-8"` on a 401; the `realm` is just a label naming the protection space the credentials belong to. `curl -u alice:s3cret` builds the header for you.

code

http · 11 lines
http
GET /reports/2024 HTTP/1.1
Host: api.example.com

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Reports API", charset="UTF-8"

GET /reports/2024 HTTP/1.1
Host: api.example.com
Authorization: Basic YWxpY2U6czNjcmV0

HTTP/1.1 200 OK

go deeper

for a junior

Recite the construction precisely — join with a colon, base64, Authorization: Basic ... — and say clearly that base64 is reversible encoding, so TLS is what protects it.

for a middle

Add the parse rule (split on the first colon), statelessness and per-request resending, and the realm/charset parameters on the 401 challenge.

for a senior

Bring in operational exposure: header scrubbing in access logs and APM, keeping secrets off command lines, and why per-request verification cost matters.

for a principal

Frame when Basic is an acceptable machine-to-machine choice (high-entropy generated secret, TLS everywhere, no lifecycle needs) versus when a token scheme with expiry, scope and revocation is required.

## What Basic authentication is Basic is the simplest scheme in the HTTP authentication framework, defined today by RFC 7617 (it updates the older RFC 2617 text). It transmits a user id and a password on each request. There is no challenge computation, no nonce, no signature — the client hands over the secret itself and the server checks it. ## Building the header value The algorithm is fully mechanical: 1. Concatenate the user id, a single `:` (colon, U+003A), and the password. 2. Encode that string to bytes (UTF-8, see the `charset` parameter). 3. Base64-encode those bytes. 4. Send `Authorization: Basic <that base64 string>`. For `alice` / `s3cret` the joined string is `alice:s3cret`, whose base64 form is `YWxpY2U6czNjcmV0`. The scheme name (`Basic`) is case-insensitive; exactly one space separates it from the credentials. ## Encoding is not protection This is the single point interviewers are checking. Base64 is a binary-to-text encoding: it maps three bytes onto four printable characters so that bytes outside the header's allowed character set (spaces, non-ASCII, control characters) can travel in an HTTP header. It uses no key, so it is trivially reversible — `echo YWxpY2U6czNjcmV0 | base64 -d` prints `alice:s3cret`. It is not encryption (no key, no confidentiality) and not hashing (it is reversible, unlike a one-way digest). Anyone who can read the request — a passive tap on plaintext HTTP, a logging proxy, an APM tool that captures headers, a browser extension — reads the password. The consequence: Basic must run inside TLS, and access logs and telemetry must scrub the `Authorization` header. RFC 7617 is explicit that Basic provides no confidentiality on its own and must be paired with a secure channel. ## The colon rule and empty values The separator is the *first* colon. Therefore the **user id must not contain a colon** — if it does, the server cannot parse the pair unambiguously and the credential is invalid. The password may contain colons freely: `bob:a:b:c` is user `bob`, password `a:b:c`. Empty halves are legal at the syntax level: `bob:` (`Ym9iOg==`) is user `bob` with an empty password, and `:onlypass` (`Om9ubHlwYXNz`) is an empty user id — some APIs use this shape to carry a single API key in the password field (`curl -u :$TOKEN`). ## Sent on every request Basic is stateless. HTTP itself has no memory between requests, and Basic adds none: there is no server-side session created by authenticating. The client therefore attaches the same `Authorization` header to every request in the protected space. Two consequences follow. First, the exposure window is not "one login" but "every single request" — any one captured request leaks the password. Second, the server pays the password-verification cost on every request, which matters when the stored password is a deliberately slow hash. ## Where the realm fits When the server wants to prompt for credentials it replies `401 Unauthorized` with `WWW-Authenticate: Basic realm="Reports API", charset="UTF-8"`. `realm` is a human-readable label that names the *protection space*: clients (and browsers) cache credentials against origin + realm and reuse them for other URLs under the same space. It carries no security by itself; it exists so a client knows which stored credential applies and so a browser dialog can say what it is asking for. `charset="UTF-8"` tells the client to encode the credentials as UTF-8 before base64. ## Tooling `curl -u alice:s3cret https://api.example.com/x` builds the header and, for Basic, sends it **preemptively** on the first request rather than waiting for a 401. `curl -u alice` prompts for the password so it does not land in your shell history or the process list — a real operational detail, since command lines are visible to other users via `ps` and end up in `~/.zsh_history`. ## When Basic is still reasonable Despite its reputation, Basic is fine for machine-to-machine calls over TLS with a high-entropy generated secret rather than a human password: it is trivially implementable in any client, needs no library, and has no token lifecycle. It is a poor fit for browser-facing user login (no logout, no session control, credentials cached by the browser, no MFA path) and for anything crossing a network you do not control unencrypted.

  • What happens if the password itself contains a colon? What if the user id does?
    A password with colons is fine: the server splits the decoded string at the first colon, so everything after it is the password. A user id containing a colon is not representable — the parse would silently move part of the name into the password — so RFC 7617 forbids it, and such a credential must be rejected.
  • Does authenticating with Basic create a session on the server?
    No. Basic is stateless: the credentials travel on every request and the server re-verifies them each time. That is why there is no protocol-level logout for Basic — the browser simply keeps replaying the cached credential — and why per-request password verification cost becomes a capacity concern.

Base64 is like writing the password in a different alphabet, not locking it in a safe: no key is needed to read it back, only the alphabet chart everyone already has.

saying these in an interview costs you the question

  • Saying base64 encrypts or hashes the password, or calling it 'encoded so it is safe'
  • Claiming the credentials are sent only once at login and a session takes over afterwards
  • Thinking the realm value adds security rather than just naming a protection space
  • Believing the separator is configurable, or that user ids may contain colons
  • Assuming Basic over plain HTTP is acceptable on a 'trusted' internal network

context

open as a page

Why does RFC 7617 require HTTP Basic authentication to be used only over a confidential channel such as TLS, and what concretely goes wrong if a service accepts Basic over plaintext HTTP?

level: middleimportance: must knowfreq 58%

basics

~20 s

Basic transmits the reusable password itself, base64-encoded, on every single request. Without TLS any observer — network tap, proxy, log — reads and replays it forever. TLS is the only thing supplying confidentiality; the scheme supplies none.

open as a page

Many HTTP clients attach the Basic `Authorization` header to the first request instead of waiting for a 401 challenge. Why is preemptive sending common, and what risks does it introduce in production?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Preemptive sending skips a wasted round trip and works with APIs that never challenge. The risk is broadcasting the password before you know the peer deserves it — to redirect targets, wrong hosts, unauthenticated endpoints, proxies and logs.

open as a page

In an HTTP challenge such as `WWW-Authenticate: Basic realm="Reports", charset="UTF-8"`, what do the realm and charset parameters actually control, and how should a password containing a character like 'ö' be encoded?

level: middleimportance: nice to knowfreq 30%

basics

~20 s

realm is a label naming the protection space, so clients know which stored credential to reuse and browsers can show it in the prompt. charset="UTF-8" — the only defined value — tells the client to encode credentials as UTF-8 before base64.

open as a page

A service authenticates every API call with HTTP Basic and verifies the supplied password against a bcrypt hash on each request. What operational consequences does that create, and how would you design around them?

level: principalimportance: nice to knowfreq 24%

basics

~20 s

Basic is stateless, so a deliberately slow password hash runs on every request. Throughput becomes cores divided by hash time, and unauthenticated traffic can exhaust CPU. Fix with short-TTL verification caching, fast hashes for high-entropy machine secrets, isolation and rate limits.

open as a page