0

I am trying to send request from angular frontend to REST controller exposed by Spring backend. REST controller has @CrossOrigin annotation.

I am using HttpClient to send requests from angular app.

Request:

  const httpOptions = {
      headers: new HttpHeaders({
        'Authorization': 'Basic ' + basicAuthHeader,
      })
    };
    return this.http.get(this.address + this.addressStorage.loginEndpoint + '/' + playerName, httpOptions);

Result:

Access to XMLHttpRequest at 'xxx' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

The same request sent by Postman gives correct response.

My assumption:

I have checked network tab using chrome dev tools: screen of network tab

Is the problem caused by the fact that OPTIONS request is being sent instead of GET request and CORS is allowing only GET method?

Assuming that my guess is correct then is adding this component to spring boot app going to solve my issue?

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            filterChain.doFilter(servletRequest, servletResponse);
        }
    } 

Unfortunately I currently can't change backend implementation so I am unable to find it out myself.

Additional info:

  registerPlayer(player: PlayerDTO): Observable<Object> {
    const httpOptions = {
      headers: new HttpHeaders({'Content-Type': 'application/json'}),
    };
    return this.http.post(this.address + this.addressStorage.createUserEndpoint, player, httpOptions);
  }

This request send to the same controller but on different endpoint returns correct responses.

hdw3
  • 495
  • 5
  • 17

1 Answers1

1

I believe your server sending Access-Control-Allow-Credentials means in angular you also need to inform your service to send request with 'Access-Control-Allow-Credentials': 'true'

Update

Credentialed requests and wildcards When responding to a credentialed request, the server must specify an origin in the value of the Access-Control-Allow-Origin header, instead of specifying the "*" wildcard. Preflighted requests

Khaled Sameer
  • 261
  • 2
  • 9
  • since you are using `Authorization` header token you don't need `Access-Control-Allow-Credentials` for your back-end `cookies` – Khaled Sameer Apr 04 '19 at 21:03
  • unfortunately, after adding `'Access-Control-Allow-Credentials': 'true'` to request's header I still get the same error. – hdw3 Apr 04 '19 at 21:10
  • can you try to replace you response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin")); since Allow-Credentials can't use wiled card – Khaled Sameer Apr 04 '19 at 21:15
  • spring component I pasted earlier is not in the backend implementation, at the moment there is only `@CrossOrigin` annotation on the controller. I can't change backend code now but is there anything I can do on frontend side to get this going or the only way is changing CORS policy in the backend app? – hdw3 Apr 04 '19 at 21:21
  • you can for testing purpose disable Cross checking ether [option 1](https://stackoverflow.com/questions/3102819/disable-same-origin-policy-in-chrome) or by [Option2](https://chrome.google.com/webstore/search/Allow-Origin?hl=en) – Khaled Sameer Apr 04 '19 at 21:30