2
votes

I have a front-end application that uses the Spring-boot, Spring security oauth2 on server side and AngularJs on client side. I also use a third-party oauth2 server. My problem is that after the expiry of the application session, sping-security redirects all request to '/login' (and that's exactly how it should be) and I got 302 status code with location to redirect on auth-server page in response header. But the redirect does not happen because I get error:

XMLHttpRequest cannot load ****://bla-bla/oauth/authorize?client_id=...andSomeAuthStuff. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '****://myipadress:8084' is therefore not allowed access.

The question is why the first entry into an application or refresh a page or logout and new login does not involve such an error and all goes well but ONLY when I get a session timeout (For example I make ajax request from dead view), CORS error occurs :-(

I reproduce the steps:

  1. On the "dead" page I make ajax request to my API (Spring-boot 1.3.3 WAR running on provided Tomcat 8)
  2. Spring intercepts the request and responds:

General:

Request URL:***//myipadress:8084/appname/login

Request Method:GET

Status Code:302 Found

Remote Address:myipadress:8084

Response headers:

Access-Control-Allow-Headers:Authorization, Content-Type, Accept, x-requested-with, Cache-Control

Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE, PUT

Access-Control-Allow-Origin:*

Access-Control-Max-Age:3600

Cache-Control:no-cache, no-store, max-age=0, must-revalidate

Location:*//authserver/oauth/authorize?client_id=******&redirect_uri=*://myipadress:8084/appname/login&response_type=code&state=BIQ68y

Pragma:no-cache

Server:Apache-Coyote/1.1

Set-Cookie:JSESSIONID=05D39263EEF7EC9E24AEE8E1E6693748; Path=/appname/; HttpOnly

X-Content-Type-Options:nosniff

X-Frame-Options:DENY

X-XSS-Protection:1; mode=block

CORS Filter:

public class SimpleCORSFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.setHeader("Access-Control-Allow-Origin", "*");
        res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        res.setHeader("Access-Control-Max-Age", "3600");
        res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
        chain.doFilter(request, res);
    }

    @Override
    public void destroy() {
    }
}

Security configuration:

@EnableOAuth2Sso
@Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.logout()
                .and().antMatcher("/**")
                .authorizeRequests()
                .anyRequest().authenticated()
                .and().csrf().disable()
                .addFilterBefore(new SimpleCORSFilter(), ChannelProcessingFilter.class);
    }

}

Log after ajax request:

2016-04-04 14:10:42.613 DEBUG 5428 --- [o-8084-exec-144] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/login' 2016-04-04 14:10:42.613 DEBUG 5428 --- [o-8084-exec-144] uth2ClientAuthenticationProcessingFilter : Request is to process authentication 2016-04-04 14:10:42.615 DEBUG 5428 --- [o-8084-exec-144] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. 2016-04-04 14:10:42.657 DEBUG 5428 --- [o-8084-exec-144] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed 2016-04-04 14:10:42.658 DEBUG 5428 --- [o-8084-exec-144] o.s.s.web.DefaultRedirectStrategy : Redirecting to '****://authserver/oauth/authorize?client_id=*****&redirect_uri=***://myipadress:8084/appname/login&response_type=code&state=iNdnBk'

3

3 Answers

0
votes

I believe you need to add the @EnableWebSecurity annotation to your CustomWebSecurityConfigurerAdapter.

0
votes

Also, I tried to go the other way and put the filter in such a way:

 @Override
    public void configure(HttpSecurity http) throws Exception {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); 
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        source.registerCorsConfiguration("/**", config);
        CorsFilter filter = new CorsFilter(source);

        http
                .logout()
                .and().antMatcher("/**")
                .authorizeRequests()
                .anyRequest().authenticated()
                .and().csrf().disable()
                .addFilterBefore(filter, ChannelProcessingFilter.class);
    }

But it also not helped and CORS headers in response all dissapeared!

0
votes

I think the reason is not in the headers, but in the status code 302 in response. How do I come to 401 instead of 302?