Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring boot + Spring Security: how to suppress the basic auth form

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?

like image 291
skapral Avatar asked Oct 05 '14 12:10

skapral


2 Answers

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());
                    }
                }
            });
}
like image 188
skapral Avatar answered Nov 05 '22 09:11

skapral


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.

like image 35
Dave Syer Avatar answered Nov 05 '22 11:11

Dave Syer