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:
- On the "dead" page I make ajax request to my API (Spring-boot 1.3.3 WAR running on provided Tomcat 8)
- 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'