httpauth Digest Authentication
Status
- Blocked by missing core module features. See section "Blockers"
- Implementation: See core review 603
Blockers
This task is blocked since HTTP-Auth requires the server to store the md5 hash of "$username:$realm:$password" (or the password in cleartext).
- This requires a "your password has expired" feature built into G2 such that G2 can build new hashes
- And this requires a storage for multiple hash-algorithm - password-hash pairs per user, which could be used by integrations as well
Problem
The current version of the httpauth module has a few weaknesses:
- Passwords transmitted in cleartext on every request.
- No automated logout, no session expiration.
- No distinction between active and passive authentication.
- Active: User should be prompted for the password.
- Passive: The browser transmits auth data on the user's behalf (e.g. a sessionId).
- Thus no real login event
- No logout mechanism - just a workaround.
Goal
Solve all the above mentioned problems by replacing the Basic authentication scheme with Digest Authentication.
With Digest authentication a nonce is associated with every HTTP-auth session. This nonce and HTTP-session have the same properties as a G2 session-id and Gallery session respectively. We can thus treat HTTP-auth the same way as normal Gallery sessions. The only difference being that the nonce is transmitted via the Authorization header while the session-id is transmitted via the Cookie header or a GET parameter.
Outline
- Use the GallerySession id as nonce.
- When sending the challenge to client, create a new GallerySession and send nonce = sessionId.
- Verify a HTTP auth request by loading the GallerySession by sessionId (nonce)
- Reject authentication if the session has expired
- Reject authentication if the user/password/nonce hash from the request don't match
- Reject authentication if the username from the request does not match the userId from the loaded GallerySession.
- Always generate a new nonce (sessionId) when sending a new challenge.
- Do not accept the same nonce for multiple authentication attempts.
- Fire login event on initial login
- Fire failed login events on failed login attempts.
Implementation Details
Sending a Digest Authentication Challenge
- Create persistent GallerySession for anonymous user to get a nonce (sessionId)
- Set "digest_auth_challenge" attribute as session data.
- Send HTTP 401 response with nonce
- Client sends response (hashes + username + echoing nonce)
- Load GallerySession by nonce (which does an implicit session expiration check)
- Verify hashes from authorization header.
- Verify that either
- userId from session corresponds to the username from the request or
- session has digest_auth_challenge flag set
- If the verification fails, delete the session and send a new challenge request
- If the digest_auth_challenge flag is set,
- trigger a login event,
- Change the active user in the session to the username from the request and
- Remove the digest_auth_challenge flag from the session
Note that the cryptographic requirements are the same for the nonce and the session-id. Therefore there is no need for a nonce-sessionId map.
- Set "stale" to FALSE in challenge where we wish to see active auth (and send a new nonce)
- Set "algorithm" to "MD5" in the challenge
- Set "domain" in challenge to cookie-path (absolute URL) to ensure that responses aren't sent to non-g2 sites on the same domain
- TODO: add "qop" and "cnonce" in future
References