Walk me through exactly what a client puts in the HTTP Authorization header when using Basic authentication, and what protection that encoding gives you.
answer
- base64(userid ':' password)
- encoding, not encryption — one-step decode
- split on FIRST colon; user id has no colon
- stateless: header on every request
- TLS mandatory; scrub Authorization from logs
basics
~20 sThe 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 sBasic 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 linesGET /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 OKgo deeper
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.
Add the parse rule (split on the first colon), statelessness and per-request resending, and the realm/charset parameters on the 401 challenge.
Bring in operational exposure: header scrubbing in access logs and APM, keeping secrets off command lines, and why per-request verification cost matters.
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