Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular4 httpclient csrf does not send x-xsrf-token

In angular documentation, it is mentioned that the angular httpclient will automatically send the value of cookie XSRF-TOKEN in the header X-XSRF-TOKEN of post request. Documentation link

But it does not send the header for me. Here is my code

Nodejs code to set the cookie

router.get('/set-csrf',function(req,res,next){     res.setHeader('Set-Cookie', "XSRF-TOKEN=abc;Path=/; HttpOnly; SameSite=Strict");         res.send();   }) 

I have used the httpclient in app.module.ts

imports: [   HttpClientModule ] 

** The above code is just for debug purpose. I do not have a set-csrf endpoint.

But it does not send any header when I send a post request. I am not able to debug.

I have added the issue in the github repository of angular too. HttpXsrfInterceptor checks if the request is GET or HEAD, or if it starts with http. If true, it skips adding the header.

Here is the code in HttpXsrfInterceptor class

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {     const lcUrl = req.url.toLowerCase();     // Skip both non-mutating requests and absolute URLs.     // Non-mutating requests don't require a token, and absolute URLs require special handling     // anyway as the cookie set     // on our origin is not the same as the token expected by another origin.     if (req.method === 'GET' || req.method === 'HEAD' || lcUrl.startsWith('http://') ||         lcUrl.startsWith('https://')) {       return next.handle(req);     }     const token = this.tokenService.getToken();      // Be careful not to overwrite an existing header of the same name.     if (token !== null && !req.headers.has(this.headerName)) {       req = req.clone({headers: req.headers.set(this.headerName, token)});     }     return next.handle(req);   } 

I am not sure why they have skipped for http/s part. Here is my issue in github

like image 1000
netuser Avatar asked Sep 04 '17 16:09

netuser


People also ask

What is X XSRF-token?

It is added to the request header for ajax requests. Popular libraries like angular and axios , automatically get value of this header from xsrf-token cookie and put it in every request header.

Should XSRF-token be Httponly?

The XSRF-TOKEN cookie is both httponly and secure, it is getting decrypted accurately and it does match up with the token stored for the session on the server.

How is CSRF token sent to client?

The client acquires a new CSRF token from the server by calling the REST endpoint baseURL/v1/csrf/tokens. The server generates a new, unique CSRF token and sends the token to the client in a custom HTTP response header.

Is CSRF needed in Spa?

CSRF token was designed for server rendering... not SPA. In SPA you already use token during authentication, so no need to use another token for CSRF. CSRF was designed as a protection for cross site calls, but API itself designed in a way that it allows request from anywhere until, they are authenticated.


2 Answers

What you are looking for is HttpClientXsrfModule.

Please read more about it here: https://angular.io/api/common/http/HttpClientXsrfModule.

Your usage should be like this:

imports: [     HttpClientModule,    HttpClientXsrfModule.withOptions({    cookieName: 'My-Xsrf-Cookie', // this is optional    headerName: 'My-Xsrf-Header' // this is optional  })  ] 

Additionally, if your code targets API via absolute URL, default CSRF interceptor will not work out of the box. Instead you have to implement your own interceptor which does not ignore absolute routes.

@Injectable() export class HttpXsrfInterceptor implements HttpInterceptor {    constructor(private tokenExtractor: HttpXsrfTokenExtractor) {   }    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {     const headerName = 'X-XSRF-TOKEN';     let token = this.tokenExtractor.getToken() as string;     if (token !== null && !req.headers.has(headerName)) {       req = req.clone({ headers: req.headers.set(headerName, token) });     }     return next.handle(req);   } } 

And finally add it to your providers:

providers: [   { provide: HTTP_INTERCEPTORS, useClass: HttpXsrfInterceptor, multi: true } ] 
like image 60
Miroslav Jonas Avatar answered Sep 22 '22 16:09

Miroslav Jonas


I suppose the correct method is withOptions. I used withConfig and got error Property 'withConfig' does not exist on type 'typeof HttpClientXsrfModule'. This is a typing issue in the documentation. You need to use "withOptions" instead HttpClientXsrfModule.withOptions({ cookieName: 'My-Xsrf-Cookie', headerName: 'My-Xsrf-Header', })

like image 23
Manu Chadha Avatar answered Sep 21 '22 16:09

Manu Chadha