Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle BadCredentialsException throwned in Spring Security's Authentication Provider

I'm using Spring-MVC and Spring-Security to develop a web application.

I'm using custom login with an AuthenticationProvider which in turn uses a UserDetailsService to match the data from the login form with the ones in the database.

I want to thrown 2 exceptions in the AuthenticationProvider, the first when the username is not present in the db, the other when the password is different.

What I'd like to do is to show in my web page the error message of the throwned exception (Wrong username or Wrong password), but I don't know where to use the catch block because the login flow is managed by Spring-Security

AuthenticationProvider

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    CustomUserDetailsService userDetails;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();

        Customer customer = userDetails.loadUserByUsername(username);

        if(customer == null) {
            throw new BadCredentialsException("Wrong username");
        }

        if(!password.equals(customer.getPassword())) {
            throw new BadCredentialsException("Wrong password");
        }

        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority(customer.getRole()));

        return new UsernamePasswordAuthenticationToken(customer, password, authorities);
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return clazz.equals(UsernamePasswordAuthenticationToken.class);
    }
}

Login page

[...]
<div class="form">
    <h2>Login</h2>
    <form th:action="@{/login}" method="POST" th:object="${customer}">
        <input type="text" placeholder="Username" name="username" th:field="*{username}"/> 
        <input type="password" placeholder="Password" name="password" th:field="*{password}"/>
        <button type="submit">Login</button>
    </form>
</div>
[...]

spring-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.0.xsd">

    <http pattern="/resources/**" security="none" />

    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/user/**" access="hasRole('USER')" />
        <form-login authentication-failure-url="/login" login-page="/login"
            login-processing-url="/login" default-target-url="/user" />
        <logout invalidate-session="true" success-handler-ref="logoutSuccessHandler" />
    </http>

    <authentication-manager>
        <authentication-provider ref="customAuthenticationProvider" />
    </authentication-manager>
</beans:beans>
like image 724
andy Avatar asked Dec 12 '25 21:12

andy


1 Answers

When using Thymeleaf, you can "catch" the authentication exception like this:

<p th:if="${param.error != null and session['SPRING_SECURITY_LAST_EXCEPTION'] != null}"
   th:text="${session['SPRING_SECURITY_LAST_EXCEPTION'].message}">
  Wrong username or password
</p>

You could probably use the standard DaoAuthenticationProvider instead of a custom class:

@Bean
public DaoAuthenticationProvider customAuthenticationProvider()
{
    DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
    provider.setUserDetailsService(userDetailsService);
    provider.setHideUserNotFoundExceptions(false);
    return provider;
}

Note that it is generally not recommended to tell whether the username exists in the system when authentication fails.

like image 178
holmis83 Avatar answered Dec 14 '25 16:12

holmis83



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!