60

Actually , our backend authenticate the request using Cookie in the request header. I know that it will refuse if I set a header "Cookie". So , is there a way to send a Cookie to the back end ?

blasrodri
  • 448
  • 5
  • 16
ad3
  • 703
  • 1
  • 5
  • 7

2 Answers2

82

I guess that there is a phase where you ask the server to authenticate you. Following this (and if the authentication is successful), the server will return a cookie in the response. The browser will store this cookie and send it again for each call.

That said, in the case of cross domain requests (CORS), you need to set the withCredentials of XHR to true to make the browser add cookies in your requests.

To enable this with Angular2, we need to extend the BrowserXhr class as described below:

@Injectable()
export class CustomBrowserXhr extends BrowserXhr {
  constructor() {}
  build(): any {
    let xhr = super.build();
    xhr.withCredentials = true;
    return <any>(xhr);
  }
}

and override the BrowserXhr provider with the extended:

bootstrap(AppComponent, [
  HTTP_PROVIDERS,
  provide(BrowserXhr, { useClass: CustomBrowserXhr })
]);

See this questions for more details:

Edit (following the freaker's comment)

From RC2, you can use the withCredentials property directly within the request configuration as described below:

this.http.get('http://...', { withCredentials: true })

Edit (following the [maxou] comment)

Remember to include withCredentials: true on every request.

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • 21
    This feature was added to angular2 now. You can now simply do something like `http.get(url, {withCredentials: true})` so this handy workaround is not needed any longer (as of 2.0.0-rc4 or earlier). – freaker Jul 03 '16 at 18:31
  • 2
    Yes, you're right. I was added in RC2. I updated my answer accordingly. Thanks very much for pointing this out ;-) – Thierry Templier Jul 04 '16 at 08:23
  • 6
    it seems to me that by using `withCredentials`, the `Set-Cookie` in the response will be set by the client, but the client still does not send the `Cookie` in the request (that was set with a previous request) – maxbellec Aug 09 '16 at 14:25
  • 3
    Any luck with this @maxou? – Kian Aug 24 '16 at 15:40
  • coresponding angular2 docs: https://angular.io/docs/ts/latest/api/http/index/RequestOptions-class.html – haja Dec 15 '16 at 09:50
  • I have the same problem as maxou, is there a solution for this? – István Feb 03 '17 at 12:25
  • 3
    @Kian use `withCredentials` in all requests – maxbellec Mar 02 '17 at 11:20
  • `withCredentials` will save you hours of headaches troubleshooting an issue that doesn't need to be troubleshooted. This is especially important when dealing with SAML tokens and using `client-sessions`. – occasl Aug 01 '17 at 20:45
  • 1
    agree with @occasl `withCredentials` is an absolute lifesaver.. saved a huge amount of time while working w/ JWT secured Node backend and Angular 4.4 – Jaron Thatcher Oct 20 '17 at 04:54
38

In Angular5 you can write a Http Interceptor:

auth.interceptor.ts

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

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor() {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone({
      withCredentials: true
  });
  return next.handle(request);
  }
}

And add to providers array of app.module

app.module.ts

import { AuthInterceptor } from './services/auth.interceptor';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpClientModule } from '@angular/common/http';
imports: [
    BrowserModule,HttpClientModule,FormsModule
  ],

providers: [
    {
    provide: HTTP_INTERCEPTORS,
    useClass: AuthInterceptor,
    multi: true,
    }
]
JavaCodeNet
  • 1,115
  • 1
  • 15
  • 21
  • 1
    This is a great approach to reduce the clutter in all of your HTTP requests. You can your application's services into the interceptor in case you need to reference anything there also. – Jon Onstott Nov 14 '18 at 22:35
  • 1
    If your angular version allows it, an Http Interceptor adding {withCredentials: true} to every request is definitely the way to go. Worked perfectly for me, using frontend Angular 7.2 and backend Laravel 5.3 – Paulo Cunha Mar 29 '19 at 08:23
  • 3
    With Flask backend I had to add the following CORS header to the response in order to make it work: `response.headers['Access-Control-Allow-Credentials'] = 'true'` – Andrew Jun 07 '20 at 12:47
  • 1
    With .NET Core/.NET 5 backend I had to add `.AllowCredentials()` to the CORS configuration in Startup.cs. The interceptor works in Angular 11 as well. I only had to change the Observable import to `import { Observable } from 'rxjs';` – MatterOfFact Feb 15 '21 at 14:14
  • Thank you @MatterOfFact! It does the trick even though I was setting before: context.Response.Headers.Add("Access-Control-Allow-Credentials", "true"); which I thought was the same. Thanks! – Piotr Śródka Jun 04 '21 at 08:16