Basic authentication does not work with XSRF token interception

635 Views Asked by At

I am implementing a simple authentication API that is configured with Spring Boot to be accessed via Basic Auth. This is a simple GET API without any parameters used only to force the browser to trigger the authentication window:

localhost:8080/api/auth

I consume this API from my Angular 7.3.10 project, which serves at

localhost:4200

At the same time I am using anti-CSRF protection, so I handle all API calls to have an additional header for the X-XSRF-TOKEN. This is my HttpInterceptor:

export class CustomHttpInterceptor implements HttpInterceptor {
    constructor(private xsrfTokenExtractor: HttpXsrfTokenExtractor) {
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (req.url.startsWith(environment.apiUrl)) {
            // send request with credential options in order to be able to read cross-origin cookies
            req = req.clone({ withCredentials: true });

            // return XSRF-TOKEN in each request's header (anti-CSRF security)
            const headerName = 'X-XSRF-TOKEN';
            let token = this.xsrfTokenExtractor.getToken() as string;
            if (token !== null && !req.headers.has(headerName)) {
                req = req.clone({ headers: req.headers.set(headerName, token) });
            }
        }
        return next.handle(req);
    }
}

Now when I call the auth endpoint within my Angular app, I get to write my credentials and then I get the following error:

Access to XMLHttpRequest at 'http://localhost:8080/api/auth' 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.

There is a preflight request when interecepting my requests to add the XSRF token and this request does not hold the Basic Auth header, even though I give my credentials properly:

preflight request part 1 preflight request part 2

Now if I remove the part that adds the XSRF token from the interceptor, then the auth request works fine after I give my credentials. Of course it does not need the XSRF token, because it is a GET request, but in the future I need to use both Basic Auth and anti-CSRF protection with POST API calls, so it is necessary to be able to make both work. Any ideas?

1

There are 1 best solutions below

0
On BEST ANSWER

As per my comment:

This is due to CORS configuration on the server side. It looks like the API is expecting credentials for the OPTIONS request. However, these requests are triggered by the browser and you cannot modify them to add custom headers, like you can see in your screenshot... so your server returns 401.

The solution is to modify the CORS config server side so that no authentication is needed for OPTIONS requests