Good day.
I am using Spring security in context of Spring boot auto-configured application. My goal is to set up basic auth in such way that standard browser's basic auth form is not shown on 401. From the Google I found out that to achieve it I need to change the default "WWW-Authenticate" header to something different than "Basic xxxxx".
To do that, I declared a filter:
@Bean
@Order(Integer.MAX_VALUE)
public Filter customAuthFilter() {
return new Filter() {
@Override
public void init(FilterConfig fc) throws ServletException {
}
@Override
public void doFilter(ServletRequest sreq, ServletResponse sresp, FilterChain fc) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) sreq;
HttpServletResponse resp = (HttpServletResponse) sresp;
fc.doFilter(req, resp);
log.info("filter");
log.info("status " + resp.getStatus());
if(resp.getStatus() == 401) {
resp.setHeader("WWW-Authenticate", "Client-driven");
}
}
@Override
public void destroy() {
}
};
From the logs I see that my filter successfully recognized by the application and takes participation in processing responses (I see the log messages from doFilter). But the actual response, received by browser, still contains the standard 'WWW-Authenticate' header. It seems that someone overrides my header, by I don't have a clue who it is exactly.
Could someone give an advice please?
Solved the problem by using custom EntryPoint:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/rest/**").authenticated()
.and().httpBasic().authenticationEntryPoint(new AuthenticationEntryPoint() {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
String requestedBy = request.getHeader("X-Requested-By");
log.info("X-Requested-By: " + requestedBy);
if(requestedBy == null || requestedBy.isEmpty()) {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.addHeader("WWW-Authenticate", "Basic realm=Cascade Realm");
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
} else {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.addHeader("WWW-Authenticate", "Application driven");
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
}
}
});
}
The Spring Security filter will be added with lowest priority as well, so probably it's upstream of yours. You could try a lower order. The conventional way to handle 401 responses is with an AuthenticationFailureHandler
but I suppose I can see why you might do it this way, given that the basic auth is already there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With