Skip to content

fail SCRAM exchange on invalid ServerSignature - #2235

Merged
hyperxpro merged 1 commit into
AsyncHttpClient:mainfrom
madib06ops:scram-verify-server-signature
Jul 16, 2026
Merged

fail SCRAM exchange on invalid ServerSignature#2235
hyperxpro merged 1 commit into
AsyncHttpClient:mainfrom
madib06ops:scram-verify-server-signature

Conversation

@madib06ops

Copy link
Copy Markdown
Contributor
  1. processScramAuthenticationInfo checks the SCRAM ServerSignature from Authentication-Info (and Proxy-Authentication-Info) but on a mismatch only logged a warning, so a response from a peer that never proved knowledge of the shared secret was still delivered as a success, voiding the mutual-authentication guarantee.
  2. RFC 7804 section 5 requires the client to treat that as an unsuccessful exchange.

Abort the request when the ServerSignature is present but invalid or unparseable, for both the origin and proxy SCRAM paths. A missing header stays warn-only, since it may legitimately arrive in chunked trailers that AHC does not read. Added a regression test that drives a full handshake and returns a corrupted ServerSignature.

@hyperxpro
hyperxpro merged commit 685173a into AsyncHttpClient:mainJul 16, 2026
13 checks passed
pullBot pushed a commit to Mu-L/async-http-client that referenced this pull request Aug 9, 2026
Motivation:
On a Digest Authentication-Info rspauth mismatch the client only logged a warning
and still delivered the response as an authenticated success, so a server that
could not prove knowledge of the shared secret was accepted. This mirrors the SCRAM
ServerSignature gap already fixed in AsyncHttpClient#2235. The expected rspauth was also computed
from future.getRealm().getCnonce(), but that realm is rebuilt for header emission
and regenerates its cnonce, so the expected value used a cnonce that was never
sent and a correct server would never have matched.
Modification:
- Verify rspauth against the cnonce actually sent, parsed from the request's own
Authorization/Proxy-Authorization header. AuthenticatorUtils.computeRspAuth now
accepts an explicit cnonce; the existing no-arg overload is unchanged.
- On a present-but-invalid rspauth, abort the request via requestSender.abort and
return true through exitAfterIntercept so the response is not delivered, exactly
as processScramAuthenticationInfo does. An absent Authentication-Info header stays
warn-only, as it may travel in chunked trailers.
Result:
A Digest mutual-auth exchange with a corrupted rspauth now fails with an
ExecutionException; a valid rspauth is accepted. Added DigestMutualAuthTest;
existing Digest and SCRAM tests are unaffected.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@madib06ops@hyperxpro