Ng2 get csrf token from cookie post it as header

After two full days of searching the Internet and reading documents and many open-ended questions from people facing the same problem, I still don’t understand how Angular 2 processes cookies (x-origin) and how to access them,

Problem: Back-end sends 2 cookies with x-csrf token and JSESSIONID inside it. My task is to store the csrf token in memory (ng2) and send it (only) back as a header (not cookie) with each message to the end.

HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Access-Control-Allow-Origin: http://localhost:4200 Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: Access-Control-Allow-Origin,Access-Control-Allow-Credentials Set-Cookie: x-csrf-token=8555257a-396f-43ac-8587-c6d489e76026; Path=/app Set-Cookie: JSESSIONID=73E38392C60370E38FBAF80143ECE212; Path=/app/; HttpOnly Expires: Thu, 12 Apr 2018 07:49:02 GMT Cache-Control: max-age=31536000 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Wed, 12 Apr 2017 07:49:02 GMT 

My partial solution: I created my own RequesstOptions class, which extends BaseRequestOptions. Added some extra headers and set the value of 'withCredentials' to true.

 export class MyRequestOptions extends BaseRequestOptions { headers: Headers = new Headers({ 'Accept': 'application/json', 'Content-Type': 'application/json', }); withCredentials = true; } 

In my HttpService, I make a message and get this:

 @Injectable() export class HttpService { constructor( protected _http: Http, protected requestOptions: RequestOptions ) { } get(url): Observable<any> { return this._http.get(url, this.requestOptions).map( res => res.json() ); } post(url: string, object: any): Observable<any> { return this._http.post(url, object, this.requestOptions).map( res => res.json() ); } } 

and in my .module application I do the magic like this:

  providers: [ { provide: RequestOptions, useClass: DocumentumDefaultRequestOptions }, { provide: XSRFStrategy, useFactory: xsrfFactory } ], 

my xsrfFactory

 export function xsrfFactory() { return new CookieXSRFStrategy('x-csrf-token', 'x-csrf-token'); } 

My partial result: At the moment, Angular sends a cookie with each request (GET and POST without discrimination) using jsessionid and x-csrf token as follows:

 POST /app/business-objects/business-objects-type HTTP/1.1 Host: localhost:8040 Connection: keep-alive Content-Length: 26 Pragma: no-cache Cache-Control: no-cache Authorization: Basic ZG1hZG1pbjphZG1pbg== Origin: http://localhost:4200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 Content-Type: application/json Accept: application/json Referer: http://localhost:4200/page Cookie: JSESSIONID=B874C9A170EFC12BEB0EDD4266896F2A; x-csrf-token=0717876e-f402-4a1c-a31a-2d60e48509d3 

My billion dollar questions:

  • How and where can I access the x-csrf token and how to add it to my requests?
  • What CookieXSRFStrategy('x-csrf-token', 'x-csrf-token'); does CookieXSRFStrategy('x-csrf-token', 'x-csrf-token'); for sure. I don’t like the feeling of a black box / understand how his documents explained. Can I access data in it?

Before sending an HTTP request, CookieXSRFStrategy searches for a cookie named XSRF-TOKEN and sets a header named X-XSRF-TOKEN with the value of this cookie.

  • It does not set the title in my case ... but why?

  • Right now I am sending a cookie to the backend using sessionid and csrf token, but what sends it? CookieXSRFStrategy or 'withCredentials' flag.

Please do not reply with one liner, for example, "document.cookie". Data is useless without metadata

+7
angular cookies csrf
source share
2 answers

Update for angular 5.0+

Http service beign is deprecated in favor of HttpClient , the CookieXSRFStrategy class CookieXSRFStrategy also deprecated, now this mission is delegated to the HttpClientXsrfModule class. If you want to customize header and cookie names, you just need to import this module as follows:

 @NgModule({ imports: [ HttpClientModule, HttpClientXsrfModule.withConfig({ cookieName: 'My-Xsrf-Cookie', headerName: 'My-Xsrf-Header', }), ] }) export class MyModule{} 

For future readers:

Ajax Answer Files

You cannot access any cookie from any Ajax response, if you check the XHR specification , you will notice that any access to the match of the Set-Cookie headers is denied:

The forbidden response header name is the header name that matches the byte case for one of:

  • Set-Cookie
  • Set-Cookie2

But my cookie is not httpOnly

Good for you, but httpOnly only states that your cookie cannot be accessed through document.cookie (see below).

API document.cookie

The only cookies you can access with javascript is document.cookie , but document.cookie refers to the cookie sent with the document (the page your script is running on) and will not be changed at any time . MDN clearly indicates the current document:

document.cookie

Get and set cookies associated with the current document. For a shared library, see this simple cookie structure.

Source: MDN

Any cookie set using an Ajax response is not relevant to the current document.

How do I implement csrf protection, then?

cookie to protect header markers is the way to go. Please note that the token you submit will be the same throughout the entire session, and it will not be changed in accordance with the wild Ajax requests sending cookies .

Web applications that use JavaScript for most of their operations can use the anti-CSRF method, which uses a policy of the same origin:

  • Upon logging in, the web application sets a cookie containing a random token that remains unchanged for the entire user session

     Set-Cookie: Csrf-token=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql; expires=Thu, 23-Jul-2015 10:25:33 GMT; Max-Age=31449600; Path=/ 
  • Client-side JavaScript reads its value and copies it to the custom HTTP header sent with each transaction request

     X-Csrf-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql 
  • The server checks for the availability and integrity of the token

The security of this method is based on the assumption that only JavaScript running in the same source can read the cookie value. JavaScript running from a fraudulent file or email will not be able to read it and copy to a custom header. Although the csrf-token cookie will be automatically sent requesting an exile, the server still expects a valid X-Csrf-Token header.

Source: Wikipedia: CSRF

With angular 2+, this mission is accomplished by the CookieXSRFStrategy class.

Original answer

How and where can I access the x-csrf token and how to add it to my requests?

Using CookieXSRFStrategy like adding it to your request. Unfortunately, the answer may be “you cannot” (see below).

What is CookieXSRFStrategy ('x-csrf token', 'x-csrf token'); I definitely do. I don’t like the feeling of a black box / understand how his documents explained.

CookieXSRFStrategy

 /** * `XSRFConfiguration` sets up Cross Site Request Forgery (XSRF) protection for the application * using a cookie. See https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) * for more information on XSRF. * * Applications can configure custom cookie and header names by binding an instance of this class * with different `cookieName` and `headerName` values. See the main HTTP documentation for more * details. * * @experimental */ export class CookieXSRFStrategy implements XSRFStrategy { constructor( private _cookieName: string = 'XSRF-TOKEN', private _headerName: string = 'X-XSRF-TOKEN') {} configureRequest(req: Request): void { const xsrfToken = getDOM().getCookie(this._cookieName); if (xsrfToken) { req.headers.set(this._headerName, xsrfToken); } } } 

A source

Basically, it reads the cookie from document.cookie and changes the Request headers accordingly.

Right now I am sending a cookie to a server with sessionid and csrf token, but what sends it? CookieXSRFStrategy or 'withCredentials' flag.

This withCredentials flag indicates that XHR should send all cookies sent (even those that were previously set using the Ajax response, but as cookies, not headers ), and there is no way to change this behavior)

It does not set the title in my case ... but why?

The cookie you are talking about is not sent with a document ( index.html ), but from another ajax request. The fact is that you cannot access the cookies set with the ajax response ( see this answer ), as this will be a security issue: a simple ajax on www.stackoverflow.com will receive a cookie from an arbitrary web page, and an attacker can easily steal it (if the header Access-Control-Allow-Origin: * present in the stackoverflow response).

On the other hand, the document.cookie API can only access cookies that are set when the document loads, and not others.

So, you should rethink the flow of interaction with the client and server on the server side, because the only cookie that you can copy to the headers is the one sent with the document, your script running (index.html).

it is not a httpOnly cookie, so it should be accessible with js, even if it is X origin

httpOnly makes cookies unavailable for the document.cookie API , but , as I told you, document.cookie refers to the file that was sent with the document, and not those sent via Ajax responses . You can make thousands of ajax calls with the Set-Cookie header in the response, document.cookie will still be the same line without any changes.

Billion dollar solution

The server should send only one x-csrf-token cookie containing the token along with the document, and you should use this token, which will be valid for the entire session for each request, using CookieXSRFStrategy . What for? because this is how it works .

+13
source share

Angular has native XSRF support , see here: https://angular.io/guide/http#security-xsrf-protection

"When executing HTTP requests, the interceptor reads the token from the default cookie XSRF-TOKEN and sets it as the HTTP header, X-XSRF-TOKEN"

So, if your server sets a cookie called XSRF-TOKEN, then it will work automatically! Do nothing on the client side. If you want to name your cookie / header again, you can also do this:

 imports: [ HttpClientModule, HttpClientXsrfModule.withConfig({ cookieName: 'My-Xsrf-Cookie', headerName: 'My-Xsrf-Header', }), ] 

And if you use spring protection, it supports angular naming conventions so you can configure this server side:

 @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .and() .authorizeRequests() .... 
0
source share

All Articles