@@ -123,6 +123,28 @@ public void validateFailedNonceExchange() throws SaslException {
123123 "Failure message: " + saslException .getMessage ());
124124 }
125125
126+ @ Test
127+ public void validateFailedNonceExchangeWithPrependingClientNonce () throws SaslException {
128+ ScramSaslServer spySaslServer = Mockito .spy (saslServer );
129+ byte [] clientFirstMsgBytes = clientFirstMessage (USER_A , USER_A );
130+ ClientFirstMessage clientFirstMessage = new ClientFirstMessage (clientFirstMsgBytes );
131+
132+ byte [] serverFirstMsgBytes = spySaslServer .evaluateResponse (clientFirstMsgBytes );
133+ ServerFirstMessage serverFirstMessage = new ServerFirstMessage (serverFirstMsgBytes );
134+ assertTrue (serverFirstMessage .nonce ().startsWith (clientFirstMessage .nonce ()),
135+ "Nonce in server message should start with client first message's nonce" );
136+
137+ //send client final message with nonce prepended with clientFirstMessage's nonce
138+ byte [] clientFinalMessage = clientFinalMessage (clientFirstMessage .nonce () + serverFirstMessage .nonce ());
139+ Mockito .doNothing ()
140+ .when (spySaslServer ).verifyClientProof (Mockito .any (ScramMessages .ClientFinalMessage .class ));
141+ SaslException saslException = assertThrows (SaslException .class ,
142+ () -> spySaslServer .evaluateResponse (clientFinalMessage ));
143+ assertEquals ("Invalid client nonce in the final client message." ,
144+ saslException .getMessage (),
145+ "Failure message: " + saslException .getMessage ());
146+ }
147+
126148 private byte [] clientFirstMessage (String userName , String authorizationId ) {
127149 String nonce = formatter .secureRandomString ();
128150 String authorizationField = authorizationId != null ? "a=" + authorizationId : "" ;
0 commit comments