title: Spring-boot-oauth2-angularjs, error with CORS after session expiry and redirect to oauth2 server
body: <p>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: </p>
  
  <blockquote>
    <p>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.</p>
  </blockquote>
  
  <p>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 :-(</p>
  
  <p><strong>I reproduce the steps:</strong></p>
  
  <ol>
  <li>On the "dead" page I make ajax request to my API (Spring-boot 1.3.3 WAR running on provided Tomcat 8)</li>
  <li>Spring intercepts the request and responds:</li>
  </ol>
  
  <p><strong>General:</strong></p>
  
  <blockquote>
    <p>Request URL:***//myipadress:8084/appname/login</p>
    
    <p>Request Method:GET</p>
    
    <p>Status Code:302 Found</p>
    
    <p>Remote Address:myipadress:8084</p>
  </blockquote>
  
  <p><strong>Response headers:</strong></p>
  
  <blockquote>
    <p>Access-Control-Allow-Headers:Authorization, Content-Type, Accept, x-requested-with, Cache-Control</p>
    
    <p>Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE, PUT</p>
    
    <p>Access-Control-Allow-Origin:*</p>
    
    <p>Access-Control-Max-Age:3600</p>
    
    <p>Cache-Control:no-cache, no-store, max-age=0, must-revalidate</p>
    
    <p><strong>Location:*</strong>//authserver/oauth/authorize?client_id=******&amp;redirect_uri=<strong>*://myipadress:8084/appname/login&amp;response_type=code&amp;state=BIQ68y</strong></p>
    
    <p>Pragma:no-cache</p>
    
    <p>Server:Apache-Coyote/1.1</p>
    
    <p>Set-Cookie:JSESSIONID=05D39263EEF7EC9E24AEE8E1E6693748; Path=/appname/; HttpOnly</p>
    
    <p>X-Content-Type-Options:nosniff</p>
    
    <p>X-Frame-Options:DENY</p>
    
    <p>X-XSS-Protection:1; mode=block</p>
  </blockquote>
  
  <p><strong>CORS Filter:</strong></p>
  
  <pre><code>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() {
      }
  }
  </code></pre>
  
  <p><strong>Security configuration:</strong></p>
  
  <pre><code>@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);
      }
  
  }
  </code></pre>
  
  <p><strong>Log after ajax request:</strong></p>
  
  <blockquote>
    <p>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=*****&amp;redirect_uri=***://myipadress:8084/appname/login&amp;response_type=code&amp;state=iNdnBk'</p>
  </blockquote>