Expected Behavior
I want to use AuthenticationManager in my own class that extends AbstractAuthenticationProcessingFilter, even if I don't call setAuthenticationManger() method in AbstractAuthenticationProcessingFilter.
Current Behavior
When I create a class that extends AbstractAuthenticationProcessingFilter, if i want to use AuthenticationManager in my class itself, AbstractAuthenticationProcessingFilter occurs errors in afterPropertiesSet method because afterPropertiesSet method in AbstractAuthenticationProcessingFilter is like this :
@Override
public void afterPropertiesSet() {
Assert.notNull(this.authenticationManager, "authenticationManager must be specified");
}
Context
I wanted to customize UsernamePasswordAuthenticationFilter, so I created a class, and extends my class to UsernamePasswordAuthenticationFilter . After that, I injected AuthenticationManager to my class, and I override getAuthenticationManager() method. At this time, an error occured, so I found this issue.
Here is my code that had in trouble.
RequestBodyAuthenticationFilter.java
@Component
public class RequestBodyAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final ObjectMapper objectMapper;
private final AuthenticationManager authenticationManager;
public RequestBodyAuthenticationFilter(AuthenticationManager manager, ObjectMapper objectMapper, AuthenticationSuccessHandler successHandler, AuthenticationFailureHandler failureHandler, Validator validator) {
authenticationManager = manager;
this.objectMapper = objectMapper;
setFilterProcessesUrl("/authenticate");
setAuthenticationSuccessHandler(successHandler);
setAuthenticationFailureHandler(failureHandler);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!HttpMethod.POST.matches(request.getMethod()))
throw new InsufficientAuthenticationException("Unsupported HTTP Method");
try {
AuthRequest authRequest = objectMapper.readValue(request.getInputStream(), AuthRequest.class);
UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken
.unauthenticated(authRequest.getId(), authRequest.getPassword());
return super.getAuthenticationManager().authenticate(token);
} catch (IOException e) {
throw new InsufficientAuthenticationException("There is no Body Data or Invalid Body Format. ");
}
}
@Override
protected AuthenticationManager getAuthenticationManager() {
return this.authenticationManager;
}
}
AuthRequest.java
public class AuthRequest {
private String id;
private String password;
public String getId() {
return id;
}
public String getPassword() {
return password;
}
}
Comment From: marcusdacoregio
Hi, @SlideAway. Is there any reason why you do not call setAuthenticationManager(...) in the constructor and pass the parameter? It feels strange that you are overriding the getAuthenticationManager() method but you are calling super.getAuthenticationManager().
Additionally, we strongly favor creating a AuthenticationFilter instead of extending the UsernamePasswordAuthenticationFilter.
With that said, it feels like this is a question that would be better suited to Stack Overflow. We prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add more detail if you feel this is a genuine bug.
Comment From: SlideAway
I apologize for my mistake. After I review my code, I found something better way.
The Reason why I extend UsernamePasswordAuthenticationFilter is that I wanted to use UsernamePasswordAuthenticationFilter in REST API for authentication logic using Spring Security's default authentication filter flow . However, UsernamePasswordAuthenticationFilter parse request parameters, so I thought that I should override this class.
But now, I noticed that overriding obtainUsername and obtainPassword methods is the better way.
Thank you for your comment.