HTTP Authentication Protocols/Schemes
See Labs @ DEV/go/.../labs/2-auth/
.
- Client requests secure resource (URI).
- Response Header (Request from Server)
- @
HTTP 401 Unauthorized
- If apropos. (Not at login form page.)
WWW-Authenticate: <type> realm=<realm>
- @
- 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)
- @ Server: PAKE2 library
- @ Browser: WASMcrypto
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 …
- No password information exchanged, as with Digest Auth protocol.
- Both server and client must own the valid registered credentials (authentication secret).
Mutual Authentication :: named messages:
- Authentication Request (
INIT
/STALE
): server requests client start.401-INIT
: start auth protocol.- Also used to indicate an auth failure.
401-STALE
: start new key exchange.
- Authenticated Key Exchange (
KEX
): used by both peers (server or client) to authenticated and share a cryptographic secret.req-KEX-C1
: sent from client.401-KEX-S1
: sent from server; an intermediate response to areq-KEX-C1
.
- Authentication Verification (
VFY
): used by both peers to verify the authentication results.req-VFY-C
: sent by client to request server authenticate and authorize the client.200-VFY-S
: response sent by server to indicate client authentication succeeded; also contains info necessary for the client to check authenticity of the server.
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.
- Server (
digest.go
) - Client (
form-login-digest.js
)
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 usesHTTP 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:
- Encrypt the client's
POST
response data. - Server can be stateless.
- Can be hardened if state is maintained.
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) )
- Server (
basic.go
) - Client (
form-login-basic.js
)
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
?)