Angular 6 does not add X-XSRF-TOKEN header to http request
I've read the docs and all the related questions on SO, but still Angular's XSRF mechanism isn't working for me: in no way I can make a POST request with the X-XSRF-TOKEN header appended automatically.
I have an Angular 6 app with a login form.
It's part of a Symfony (PHP 7.1) website, and the Angular app page, when served from Symfony, sends the correct Cookie (XSRF-TOKEN
):
My app.module.ts includes the right modules:
// other imports...
import {HttpClientModule, HttpClientXsrfModule} from "@angular/common/http";
// ...
@NgModule({
declarations: [
// ...
],
imports: [
NgbModule.forRoot(),
BrowserModule,
// ...
HttpClientModule,
HttpClientXsrfModule.withOptions({
cookieName: 'XSRF-TOKEN',
headerName: 'X-CSRF-TOKEN'
}),
// other imports
],
providers: [],
entryComponents: [WarningDialog],
bootstrap: [AppComponent]
})
export class AppModule {
}
Then, inside a Service's method, I'm making the following http request (this.http
is an instance of HttpClient
):
this.http
.post<any>('api/login', {'_username': username, '_pass': password})
.subscribe(/* handler here */);
The post request never sends the X-XSRF-TOKEN header. Why?
The problem once again is Angular's poor documentation.
The fact is, Angular will add the X-XSRF-TOKEN
header only if the XSRF-TOKEN
cookie was generated server-side with the following options:
- Path =
/
- httpOnly =
false
(this is very important, and fully undocumented)
Besides, the Angular app and the URL being called must reside on the same server.
Reference: this Angular Github issue
On my team, the problem was that we were using an absolute path instead of a relative path.
So do not use an absolute path like:
this.http.post<any>("https://example.com/api/endpoint",data)
Use
this.http.post<any>("api/endpoint",data)
Or use
this.http.post<any>("//example.com/api/endpoint",data)
This is because absolute paths are explicitly ignored by Angular code on HttpClientXsrfModule (see)
After struggling for countless hours, the solution that worked for us was changing the request (in Angular) from 'https://example.com' to '//example.com'.
None of the other solutions worked for us.