1515 */
1616package org .springframework .security .oauth2 .server .authorization .web ;
1717
18+ import java .nio .charset .StandardCharsets ;
19+
1820import javax .servlet .FilterChain ;
1921import javax .servlet .http .HttpServletRequest ;
2022import javax .servlet .http .HttpServletResponse ;
3335import org .springframework .security .authentication .AuthenticationManager ;
3436import org .springframework .security .core .Authentication ;
3537import org .springframework .security .core .context .SecurityContextHolder ;
38+ import org .springframework .security .crypto .codec .Hex ;
3639import org .springframework .security .oauth2 .core .ClientAuthenticationMethod ;
3740import org .springframework .security .oauth2 .core .OAuth2AuthenticationException ;
3841import org .springframework .security .oauth2 .core .OAuth2Error ;
@@ -130,6 +133,7 @@ public void doFilterWhenRequestDoesNotMatchThenNotProcessed() throws Exception {
130133 this .filter .doFilter (request , response , filterChain );
131134
132135 verify (filterChain ).doFilter (any (HttpServletRequest .class ), any (HttpServletResponse .class ));
136+ verifyNoInteractions (this .authenticationConverter );
133137 }
134138
135139 @ Test
@@ -142,6 +146,7 @@ public void doFilterWhenRequestMatchesAndEmptyCredentialsThenNotProcessed() thro
142146 this .filter .doFilter (request , response , filterChain );
143147
144148 verify (filterChain ).doFilter (any (HttpServletRequest .class ), any (HttpServletResponse .class ));
149+ verifyNoInteractions (this .authenticationManager );
145150 }
146151
147152 @ Test
@@ -164,6 +169,46 @@ public void doFilterWhenRequestMatchesAndInvalidCredentialsThenInvalidRequestErr
164169 assertThat (error .getErrorCode ()).isEqualTo (OAuth2ErrorCodes .INVALID_REQUEST );
165170 }
166171
172+ // gh-889
173+ @ Test
174+ public void doFilterWhenRequestMatchesAndClientIdContainsNonPrintableASCIIThenInvalidRequestError () throws Exception {
175+ // Hex 00 -> null
176+ String clientId = new String (Hex .decode ("00" ), StandardCharsets .UTF_8 );
177+ assertWhenInvalidClientIdThenInvalidRequestError (clientId );
178+
179+ // Hex 0a61 -> line feed + a
180+ clientId = new String (Hex .decode ("0a61" ), StandardCharsets .UTF_8 );
181+ assertWhenInvalidClientIdThenInvalidRequestError (clientId );
182+
183+ // Hex 1b -> escape
184+ clientId = new String (Hex .decode ("1b" ), StandardCharsets .UTF_8 );
185+ assertWhenInvalidClientIdThenInvalidRequestError (clientId );
186+
187+ // Hex 1b61 -> escape + a
188+ clientId = new String (Hex .decode ("1b61" ), StandardCharsets .UTF_8 );
189+ assertWhenInvalidClientIdThenInvalidRequestError (clientId );
190+ }
191+
192+ private void assertWhenInvalidClientIdThenInvalidRequestError (String clientId ) throws Exception {
193+ when (this .authenticationConverter .convert (any (HttpServletRequest .class ))).thenReturn (
194+ new OAuth2ClientAuthenticationToken (clientId , ClientAuthenticationMethod .CLIENT_SECRET_BASIC , "secret" , null ));
195+
196+ MockHttpServletRequest request = new MockHttpServletRequest ("POST" , this .filterProcessesUrl );
197+ request .setServletPath (this .filterProcessesUrl );
198+ MockHttpServletResponse response = new MockHttpServletResponse ();
199+ FilterChain filterChain = mock (FilterChain .class );
200+
201+ this .filter .doFilter (request , response , filterChain );
202+
203+ verifyNoInteractions (filterChain );
204+ verifyNoInteractions (this .authenticationManager );
205+
206+ assertThat (SecurityContextHolder .getContext ().getAuthentication ()).isNull ();
207+ assertThat (response .getStatus ()).isEqualTo (HttpStatus .BAD_REQUEST .value ());
208+ OAuth2Error error = readError (response );
209+ assertThat (error .getErrorCode ()).isEqualTo (OAuth2ErrorCodes .INVALID_REQUEST );
210+ }
211+
167212 @ Test
168213 public void doFilterWhenRequestMatchesAndBadCredentialsThenInvalidClientError () throws Exception {
169214 when (this .authenticationConverter .convert (any (HttpServletRequest .class ))).thenReturn (
@@ -179,6 +224,7 @@ public void doFilterWhenRequestMatchesAndBadCredentialsThenInvalidClientError()
179224 this .filter .doFilter (request , response , filterChain );
180225
181226 verifyNoInteractions (filterChain );
227+ verify (this .authenticationManager ).authenticate (any ());
182228
183229 assertThat (SecurityContextHolder .getContext ().getAuthentication ()).isNull ();
184230 assertThat (response .getStatus ()).isEqualTo (HttpStatus .UNAUTHORIZED .value ());
0 commit comments