Search code examples
spring-bootspring-security

Spring Boot - How do I invalidate a successful authentication in AuthenticationFilter based on list of returned user authorities


In my Spring Boot app, I have AuthenticationFilter class with attemptAuthentication and successfulAuthentication methods that handle authentication:

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

    Authentication authentication = null;

    UserLoginRequestModel userLoginRequestModel = extractCredentials(request);
    UsernamePasswordAuthenticationToken userToken = new UsernamePasswordAuthenticationToken(
            userLoginRequestModel.getUsername(), userLoginRequestModel.getPassword(), new ArrayList<>());

    authentication = authenticationManager.authenticate(userToken);
    
    // At this point, and once user is authenticated, I get a list of granted authorities.
    // I want to cancel the authentication (make user no longer authenticated) if the list of authorities
    // does not contain authorities I need.
    // for example, I want this user to be authenticated only if authorities contain
    // AUTHORITY-1, AUTHORITY-2, but otherwise make the authentication as NOT AUTHENTICATED.

    return authentication;
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {

    String userId = ((UserDetails)authentication.getPrincipal()).getUsername();

    Collection<GrantedAuthority> grantedAuthories = authentication.getAuthorities();

    // ... do some stuff with reponse
}

My authentication is working as expected and I am able to authenticate successfully.

However, being still new with Spring Security, I am trying to figure out how to invalidate a successful authentication based on below.

Once user is authenticated in the attemptAuthentication method, I want to be able to cancel that authentication based on list of user authorities returned to me.

I want to do something like in this pseudocode:

if (authentication.getAuthorities() does not contain AUTHORITY-1) {
  set user back to not authenticated  // HOW DO I DO THIS PART?
}

I have looked at some properties of Authentication object and I see it has setAuthenticated(false) but doint that changes nothing, the successfulAuthentication method is still invoked as when a user is successfully authenticated.

How do I invalidate the authentication object returned in attemptAuthentication method?


Solution

  • According to the docs, the implementation of the attemptAuthentication method should do one of the following:

    1. Return a populated authentication token for the authenticated user, indicating successful authentication
    2. Return null, indicating that the authentication process is still in progress. Before returning, the implementation should perform any additional work required to complete the process.
    3. Throw an AuthenticationException if the authentication process fails

    To invalidate the authentication, AuthenticationException should be thrown. Since it's an abstract class, it cannot be thrown directly, you can create your own concrete subclass, or use one of the existing ones listed here.