include::../description.adoc[] include::../ask-yourself.adoc[] include::../recommended.adoc[] == Sensitive Code Example In a Spring-security web application the username leaks when: * The string used as argument of https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/core/userdetails/UserDetailsService.html[loadUserByUsername] method is used in an exception message: ---- public String authenticate(String username, String password) { // .... MyUserDetailsService s1 = new MyUserDetailsService(); MyUserPrincipal u1 = s1.loadUserByUsername(username); if(u1 == null) { throw new BadCredentialsException(username+" doesn't exist in our database"); // Sensitive } // .... } ---- * https://docs.spring.io/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/core/userdetails/UsernameNotFoundException.html[UsernameNotFoundException] is thrown (except when it is in the loadUserByUsername method): ---- public String authenticate(String username, String password) { // .... if(user == null) { throw new UsernameNotFoundException("user not found"); // Sensitive } // .... } ---- * https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.html#setHideUserNotFoundExceptions-boolean-[HideUserNotFoundExceptions] is set to false: ---- DaoAuthenticationProvider daoauth = new DaoAuthenticationProvider(); daoauth.setUserDetailsService(new MyUserDetailsService()); daoauth.setPasswordEncoder(new BCryptPasswordEncoder()); daoauth.setHideUserNotFoundExceptions(false); // Sensitive builder.authenticationProvider(daoauth); ---- == Compliant Solution In a Spring-security web application: * the same message should be used regardless of whether it is the wrong user or password: [source,java] ---- public String authenticate(String username, String password) throws AuthenticationException { Details user = null; try { user = loadUserByUsername(username); } catch (UsernameNotFoundException | DataAccessException e) { // Hide this exception reason to not disclose that the username doesn't exist } if (user == null || !user.isPasswordCorrect(password)) { // User should not be able to guess if the bad credentials message is related to the username or the password throw new BadCredentialsException("Bad credentials"); } } ---- * https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.html#setHideUserNotFoundExceptions-boolean-[HideUserNotFoundExceptions] should be set to true: [source,java] ---- DaoAuthenticationProvider daoauth = new DaoAuthenticationProvider(); daoauth.setUserDetailsService(new MyUserDetailsService()); daoauth.setPasswordEncoder(new BCryptPasswordEncoder()); daoauth.setHideUserNotFoundExceptions(true); // Compliant builder.authenticationProvider(daoauth); ---- include::../see.adoc[] ifdef::env-github,rspecator-view[] ''' == Implementation Specification (visible only on this page) include::../message.adoc[] ''' == Comments And Links (visible only on this page) include::comments-and-links.adoc[] endif::env-github,rspecator-view[]