I'm writing an application that communicates with a backend API that requires a XSRF-TOKEN
header be set on every request. I've achieved that with the following HTTP interceptor:
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
const modifiedReq = request.clone({
headers: request.headers.set('X-XSRF-TOKEN', this.cookieService.get('XSRF-TOKEN')),
});
return next.handle(modifiedReq);
}
Now I need to handle the case where the XSRF-TOKEN
cookie is not yet set. In this case I will need to preflight the request that I'm sending with one that hits a specific /csrf
endpoint on the backend API, which will return a Set-Cookie
header to set XSRF-TOKEN
.
As a quick and dirty test (without refactoring to remove duplicate code) I tried this:
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
if (!this.cookieService.check('XSRF-TOKEN')) {
this.apiService.csrf().subscribe(() => {
const modifiedReq = request.clone({
headers: request.headers.set('X-XSRF-TOKEN', this.cookieService.get('XSRF-TOKEN')),
});
return next.handle(modifiedReq);
});
}
const modifiedReq = request.clone({
headers: request.headers.set('X-XSRF-TOKEN', this.cookieService.get('XSRF-TOKEN')),
});
return next.handle(modifiedReq);
}
But this obviously has the consequence of an infinite loop of requests to the /csrf
endpoint, as each HTTP request inside the interceptor is intercepted itself...
How can I achieve what I'm going for here?
Just let the request to /csrf
complete without intercepting it:
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
if (request.url === '/csrf') {
return next.handle(request);
}
if (!this.cookieService.check('XSRF-TOKEN')) {
this.apiService.csrf().subscribe(() => {
const modifiedReq = request.clone({
headers: request.headers.set('X-XSRF-TOKEN', this.cookieService.get('XSRF-TOKEN')),
});
return next.handle(modifiedReq);
});
}
const modifiedReq = request.clone({
headers: request.headers.set('X-XSRF-TOKEN', this.cookieService.get('XSRF-TOKEN')),
});
return next.handle(modifiedReq);
}