7

I have a Spring Boot back-end application that runs on port 8888 and an Angular front-end app that runs on 4200.

In my Spring Boot application i've defined the following bean to handle CORS:

@Bean
public WebMvcConfigurer webMvcConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**");
        }
    };
}

And my HttpSecurity configuration looks like this:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .cors()
        .and()
        .csrf().disable()
        // ... the rest of the config
}

With this configuration everything works fine, i can successfully call my API from the Angular app.

But i would like to enable CSRF, so i've changed the security config to the following:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .cors()
        .and()
        .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        // ... the rest of the config
}

And i've added the following HttpInterceptor to my Angular app:

constructor(private tokenExtractor: HttpXsrfTokenExtractor) { }

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = this.tokenExtractor.getToken();
    if (token) {
        req = req.clone({ setHeaders: { 'X-XSRF-TOKEN': token } });
    }
    return next.handle(req);
}

The problem is tokenExtractor.getToken() always returns null.

The corresponding request and response headers look like this:

enter image description here

The XSRF-TOKEN response cookie is present.

I cannot figure out what the problem is.

I've tried importing the HttpClientXsrfModule in my Angular app, but it doesn't make any difference.

I'd really appreciate any advice.

justanoob
  • 1,797
  • 11
  • 27
  • Hope this helps https://stackoverflow.com/questions/48002670/angular-5-unable-to-get-xsrf-token-from-httpxsrftokenextractor – Wit Wikky Mar 15 '21 at 12:42

4 Answers4

0

No need. You can use chrome nosecurity or install Allow-Control-Allow-Origin plugin is ok to resolve the problem.

NhutLe
  • 95
  • 8
  • I think it's bad advice to circumvent security things; and how should this work with other users of the application? – P.J.Meisch Mar 09 '19 at 15:19
  • we use the method in dev environment. we can't meet cross domain in AT or production environment. – NhutLe Mar 09 '19 at 15:41
  • but that's not the environment that the question addresses. So while your answer may be enough for your setup, it probalby does not answer the OPs question. – P.J.Meisch Mar 09 '19 at 16:33
0

I'm using this code in my Spring Boot apps and it works great with Angular

@Component public class SimpleCORSFilter implements Filter {

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

    chain.doFilter(req, res);
}

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}

Hope it helps :)

MunkMurray
  • 28
  • 3
0

as said in the documentation [ ...you can enable cross-origin resource sharing (CORS) from either in individual controllers or globally...]

  • Controller Method CORS Configuration: can be enabled using @CrossOrigin annotation
  • Global CORS configuration:
@Configuration
public class CorsConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer(){
        return new WebMvcConfigurer(){
            @Override
            public void addCorsMappings(CorsRegistry registry){

                registry.addMapping("/**")
                        .allowedOrigins("*")
                        .allowedMethods("*")
                        .allowedHeaders("*").maxAge(3600);

            }
        };
    }
}

Dima Kozhevin
  • 3,602
  • 9
  • 39
  • 52
MedMahmoud
  • 117
  • 1
  • 2
  • 15
0

In fact Spring handles the server side implementation here. All you have to do is add the .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) config, as you did.

The security pattern that Spring implements for you here, is the "cookie-to-header" pattern. Spring adds a cookie named XSRF-TOKEN to the response of your GET request. Let's say the value is aa5f7a64-cf4d-4706-b5aa-bcdec2b41798.

When you try to do a POST request, Spring will return a 403 Forbidden, unless you add a header with key X-XSRF-TOKEN and the value of the cookie you got from the GET request. For our example, that would be aa5f7a64-cf4d-4706-b5aa-bcdec2b41798.

Spring will check whether the value of the cookie and of the header are the same. Only if they are the same, the request will pass. Otherwise you get a 403 Forbidden.