Reputation: 10263
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?
Upvotes: 41
Views: 60887
Reputation: 10263
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:
/
false
(this is very important, and fully undocumented)Besides, the Angular app and the URL being called must reside on the same server.
Refer this Angular Github issue
Upvotes: 54
Reputation: 924
For Spring Boot users this below taken me a while:
Besides, the Angular app and the URL being called must reside on the same server.
I was testing my solution on my localhost with apps on different ports and it works like it was the same origin.
But the problem happened after I changed context-path: /api
and this was different from origin thats why I suppose Angular won't add XSRF
token to request, so I need to add:
final CookieCsrfTokenRepository cookieCsrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
cookieCsrfTokenRepository.setCookiePath("/");
to set up them same origin
Here is complex solution for diffrent context-path
Upvotes: 1
Reputation: 197
request = request.clone({
withCredentials: true
});
In InterceptService, this works with me
Upvotes: 3
Reputation: 731
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)
Upvotes: 38
Reputation: 61
You should put on the service on the frontend this { withCredentials: true }
Ex:
this.http.put<class>(url, body, { withCredentials: true });
Upvotes: 6
Reputation: 421
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.
Upvotes: 9
Reputation: 6658
Slightly off topic, but for others who come here, I resolved this issue in the back end by the following (for spring-boot
)
/**
* CORS config - used by cors() in configure() DO NOT CHANGE the METDHO NAME
*
* @return
*/
@Bean()
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Lists.newArrayList("http://localhost:4200"));
configuration.setAllowedMethods(Lists.newArrayList("GET", "POST", "OPTIONS"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Lists.newArrayList("x-xsrf-token", "XSRF-TOKEN"));
configuration.setMaxAge(10l);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
Upvotes: 5
Reputation: 19012
Make sure, your server allows X-CSRF-Token
headers on when browser requests OPTIONS
method.
Example:
Access-Control-Allow-Headers: X-CSRF-Token, Content-Type
Reference: MDN Docs
Upvotes: 3