HTTP Authentication Protocols/Schemes

See Labs @ DEV/go/.../labs/2-auth/ .

HTTP Authentication Flow (PNG)

  1. Client requests secure resource (URI).
  2. Response Header (Request from Server)
  3. Request Header (Response from Client)

Note the WWW-Authenticate header triggers a browser popup; "Authentication Required"; a hard-coded login form.

Reference: MDN

Mutual Auth | RFC 8120 (2017)

A general framework providing a strong cryptographic solution for password authentications; password-based authenticated key exchange (PAKE). Default mode of SSH. When using CA certificates, this protocol is called Mutual TLS (mTLS). Isn't as popular as JWT-based schemes, for web applications.

[Digest Auth works, but] … powerful computers … offline password dictionary attack … threatening the effectiveness of such hash-based password protections.

[Even with TLS (HTTPS),] … if the users are fraudulently routed to a "wrong Website" via some kind of social engineering attack (e.g., phishing) and tricked into performing authentication on that site

Mutual Authentication :: named messages:

HMAC/SCRAM (SCRAM-SHA-256) | RFC 7804 (2016)

Salted Challenge Response HTTP Authentication Mechanism (SCRAM)

Challenge/response testing an assertion against its keyed digest (HMAC), so both client and server must have a pre-shared private key. Commonly used to secure APIs.

@ AWS APIs :: AWS4-HMAC-SHA256

Digest Auth | RFC 7616 (2015) | RFC 2617, Section 3 (1999)

The Digest scheme is based on a simple challenge-response paradigm … challenges using a nonce value [to mitigate replay attacks] … response contains an unkeyed digest: user:pass:nonce:HTTPmethod:requestURI.

Requires (pre-existing) shared secret (user:pass) known to both client and server, so this scheme is useful for Login sessions, but not for Sign up. Example @ RFC 7617, Section 3

SHA512(user:pass:keyL:keyU)

In this version, a cnonce is sent back from client. Since server must maintain state anyway, the scheme can add (server-sent) nonce requirement too.

Basic Auth | RFC 7617 (2015) | RFC 2617 (1999)

This Golang BasicAuth() function is not used here; just a reference …

func (r *Request) BasicAuth() (username, password string, ok bool)

BasicAuth returns the username and password provided in the request's Authorization header, if the request uses HTTP Basic Authentication. See RFC 2617, Section 2.

User ID and password are passed over the network as clear text (user:pass), so HTTPS/TLS required. However, ...

Modified scheme features:

This is a sort of Digest Auth scheme RFC 2617, Section 3, but with the "private key" generated client-side and sent (obfuscated) along with the (challenge) response. Also, server can be stateless, unlike Digest Auth.

XOR( XOR( user:pass, H(keyL) ), H(keyL+keyU) )

The form's submit event is intercepted. The keys are concatenated (e.g., user:pass), creating the payload. This is XOR'd with a one-time login key H(keyL); a message digest (SHA-512) of a randomly genterated number, per Window.crypto. The product is again XOR'd, but with a similarly constructed string based on KeyL and User Agent, H(keyL+keyU). Finally, the payload is base64 encoded and then inserted into a hidden form key.

To decipher server-side, the one-time login key is received as a cookie (H(keyL)), and the other key is regenerated from that one-time key concatenated with the UA Header. The one-time key (H(keyL)) cookie is deleted upon server response. The intent is for the server to respond with an auth cookie, __Host-0: HMAC(user:pass), or perhaps a session cookie __Host-0: HMAC(session:user:pass).

The cipher payload is sent from the client per AJAX/POST under its own key (ajax). Prior to the delayed form.submit() action, the user-entered data (user and pass) are cleared.

All the parameters required to defeat this are in the request, and so it remains vulnerable. The difference is that the payload is not sent in plaintext; its recovery requires knowledge of the hash and XOR scheme (or a very good guess), and performing its required multi-step processing on the base64-decoded payload.

The scheme can be hardened by using a server-sent cookie (H(keyL)), sent along with the login form (page). Such a key would be absent from the subsequent client response (login request). This, however, requires the server to maintain state per user login. (Can handle per http.context?)