3

I am currently working on an Angular4 app. Now I want to implement XSRF protection. In Response header cookies, I am getting "XSRF-TOKEN" and I need to send "X-XSRF-TOKEN" in next Request header cookies. As mentioned in official Angular document, Angular is taking care of this. But in my case, angular is not handling it. So I created following custom XsrfInterceptor to attach "X-XSRF-TOKEN" with response header.

import { NgModule, Injectable } from '@angular/core';
import { Observable } from "rxjs/Observable";
import { HttpRequest, HttpHandler, HttpEvent, HttpXsrfTokenExtractor, HttpInterceptor } from "@angular/common/http";

@Injectable()
export class XsrfInterceptor implements HttpInterceptor {

    constructor(private tokenExtractor: HttpXsrfTokenExtractor) {
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const headerName = 'X-XSRF-TOKEN';
        console.log("xsrf intercepter called");
        let requestToForward = req;
        let token = this.tokenExtractor.getToken() as string;
        console.log(token);
        if (token !== null) {
            requestToForward = req.clone({ setHeaders: {headerName: token } });
        }
        return next.handle(requestToForward);
    }
}

And in my main module, I included it in provider,

providers: [
    LoginService,
    AuthGuardLogin,
    { provide: HTTP_INTERCEPTORS, useClass: XsrfInterceptor,  multi: true }      
], 

But unfortunatley it is not working. I think my aopplication is not calling intercept method of custom Intercepter (it is not printing console.log('xsrf intercepter called')).

My http header is below:

let httpHeader = new RequestOptions({
            headers: new Headers({
                'Content-Type': 'application/json',
                'x-auth-token': this.authToken
            })
        })

In response header:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Access-Control-Allow-Origin, Access-Control-Allow-Headers, Accept, X-XSRF-TOKEN, XSRF-TOKEN, X-Requested-By, Content-Type, Origin, Authorization, X-Requested-With, x-auth-token, OPTIONS
Access-Control-Allow-Methods:POST, GET, PUT, OPTIONS
Access-Control-Allow-Origin:http://localhost:7070
Access-Control-Expose-Headers:x-auth-token, XSRF-TOKEN, X-XSRF-TOKEN
Access-Control-Max-Age:3600
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Date:Fri, 24 Nov 2017 06:42:20 GMT
Expires:0
Pragma:no-cache
Referrer-Policy:same-origin
Set-Cookie:XSRF-TOKEN=63f66e2a-1ad0-4641-8f36-27c16734a676;path=/mfleet;HttpOnly
Transfer-Encoding:chunked
x-auth-token:8d06b1da-c35b-42ea-ac28-eae51f3dd74d
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block

Next Request Header:

Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.9
Connection:keep-alive
Content-Type:application/json
Cookie:XSRF-TOKEN=63f66e2a-1ad0-4641-8f36-27c16734a676  **//this should be X-XSRF-TOKEN**
Host:localhost:7070
Referer:http://localhost:7070/dist/
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
x-auth-token:8d06b1da-c35b-42ea-ac28-eae51f3dd74d

I am using following versions of angular libraries:

"@angular/animations": "^4.4.5",
    "@angular/cdk": "^2.0.0-beta.8",
    "@angular/common": "^4.0.0",
    "@angular/compiler": "^4.0.0",
    "@angular/core": "^4.0.0",
    "@angular/forms": "^4.0.0",
    "@angular/http": "4.0.0",
    "@angular/material": "^2.0.0-beta.8",
    "@angular/platform-browser": "^4.0.0",
    "@angular/platform-browser-dynamic": "^4.0.0",
    "@angular/router": "^4.0.0",
s sharif
  • 724
  • 1
  • 10
  • 19

1 Answers1

6

Angular is taking care of XSRF only if you import the right module. And only since 4.3 which implement new http client and interceptors.

You should update angular to at least 4.3.0 (i recommend to upgrade to 5.0.0 cause this is needed for last versions of material2) then import HttpClientXsrfModule in your app module. Then it should work out of the box.

Regards

Pierre Mallet
  • 7,053
  • 2
  • 19
  • 30
  • Thanks for your help. I have implemented as per your suggestion. But it is not working. Please check following code and correct me if I am missing something? "@angular/animations": "4.4.5", "@angular/cdk": "^2.0.0-beta.8", "@angular/common": "4.3.0", "@angular/compiler": "4.3.0", "@angular/core": "4.3.0", "@angular/forms": "4.3.0", "@angular/http": "4.3.0", "@angular/material": "^2.0.0-beta.8", "@angular/platform-browser": "4.3.0", "@angular/platform-browser-dynamic": "4.3.0", "@angular/router": "4.3.0", – s sharif Nov 24 '17 at 10:07
  • 1
    imports:[ //other modules... HttpClientXsrfModule.withOptions({ cookieName: 'XSRF-TOKEN', headerName: 'X-XSRF-TOKEN' }) ] – s sharif Nov 24 '17 at 10:11
  • are you using new module HttpClientModule to make your https calls ? Interceptor will only be used with this module – Pierre Mallet Nov 24 '17 at 10:16
  • let token = this.tokenExtractor.getToken() as string; is always returning null value. Am I missing something? – s sharif Nov 25 '17 at 09:24
  • Since your configuration is standard ( cf : https://angular.io/guide/http#security-xsrf-protection ) you should just import HttpClientModule, HttpClientXsrfModule and thats all. You should not have to create an interceptor since HttpClientXsrfModule do that for you, and should not have to call the tokenExtractor manually. – Pierre Mallet Nov 27 '17 at 07:59
  • in my case request and response, cookie path is different. should I set path explictly? – s sharif Nov 27 '17 at 11:44
  • in the responses there is not need to cookie. The xsrf token is set in headers "from doc" => On subsequent requests the server can verify that the cookie matches the X-XSRF-TOKEN HTTP header https://angular.io/guide/http#security-xsrf-protection – Pierre Mallet Nov 27 '17 at 13:01
  • Hi. I am facing the same issue and followed all the steps mentioned above, but issue persists. Steps the I followed:- – saivishal vangala Feb 23 '21 at 14:54
  • Hi. I am facing the same issue and followed all the steps mentioned above, but the issue persists. Steps the I followed:- 1. added HttpClientModule, HttpClientXsrfModule.withOptions({ cookieName: 'XSRF-TOKEN', headerName: 'X-XSRF-TOKEN' }) in imports When i run both angular and spring boot applications on localhost on different ports then i have received XSRF-TOKEN in 'Set-Cookie' but could not able to set this as 'X-XSRF-TOKEN' in request header. When i run both on tomcat server on same port, then i can see Cookie: XSRF-TOKEN=8517a625-437b-4467-a99f-ed8e03e0d2ab in request header. – saivishal vangala Feb 23 '21 at 15:03
  • Appreciate your help here to get a 'X-XSRF-TOKEN' in request header instead of Cookie: XSRF-TOKEN=8517a625-437b-4467-a99f-ed8e03e0d2ab – saivishal vangala Feb 23 '21 at 15:04