The primary reason for classes needing to override attemptAuthentication is that AbstractAuthenticationProcessingFilter doesn't have a way to get the authentication request to then pass it AuthenticationManager.

Adding AuthenticationConverter will allow applications to favor composition over inheritance by giving a default implementation of attemptAuthentication:

Authentication authentication = this.authenticationConverter.convert(request);
if (authentication == null) {
    return null;
}
Authentication result = this.authenticationManager.authenticate(authentication);
if (result == null) {
    throw new ServletException("AuthenticationManager should not return null Authentication object.");
}
return result;

This is the same implementation of attemptAuthentication as AuthenticationFilter.