Angular withCredentials is not sending cookies
Asked Answered
L

1

11

I am using Angular 8, with old backend (ASP.NET MVC 5 Framework) NOT CORE
I am trying to send the cookies of the website so the request from the angular website considered authenticated

I created an interceptor for this

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

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

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

}

here is the code of the request

private getDefaultConfiguration(): configurationsType {
  return {
    observe: 'response',
    responseType: 'json',
    headers: new HttpHeaders().set('Content-Type', 'application/json')
  };
}

public async get(endpoint: string, params: HttpParams = undefined) {
  const options = this.getDefaultConfiguration();
  if (params !== undefined)
    options.params = params;

  const response: HttpResponse<object> = await this.http.get(endpoint, options).toPromise();
  return await this.errorCheck(response);
}

I can confirm that the interceptor is executing by a console.log statement
the problem is that I am not receiving the cookies in the request (by the way Http Get not Post) and my request is considered to be unauthenticated.

I am using the following Filter for CORS problem

public class AllowCrossSiteAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        HttpResponseBase response = filterContext.RequestContext.HttpContext.Response;

        response.AddHeader("Access-Control-Allow-Origin", "http://localhost:4200");
        response.AddHeader("Access-Control-Allow-Headers", "*");
        response.AddHeader("Access-Control-Allow-Methods", "*");
        response.AddHeader("Access-Control-Allow-Credentials", "true");

        base.OnActionExecuting(filterContext);
    }
}

I register the filter globally,

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new AllowCrossSiteAttribute());
    }
}

here is the cookie that I expect to be sent in the header, this snippet is from the login method

var ticket = new FormsAuthenticationTicket(SessionHelper.DefaultSession().KullaniciAdi, model.RememberMe, timeout);
string encrypted = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encrypted)
{
    Expires = DateTime.Now.AddMinutes(timeout),
    HttpOnly = true // cookie not available in javascript.
};

Response.Cookies.Add(cookie);

return RedirectToAction("Index", "Home");

and here is the cookie in the chrome

enter image description here if you need any more information please ask me in the comment and I will provide that.

Update

  1. I check it out this article and I applied the same-site attribute of the set-cookie to none, but this still does not solve the problem.

  2. I updated the [AllowCrossSiteAttribute] to be like this, because of completely another problem I was receiving in angular

public class AllowCrossSiteAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        HttpResponseBase response = filterContext.RequestContext.HttpContext.Response;

        response.AddHeader("Access-Control-Allow-Origin", "http://localhost:4200");
        response.AddHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
        response.AddHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
        response.AddHeader("Access-Control-Allow-Credentials", "true");

        base.OnActionExecuting(filterContext);
    }
}

  1. In the OnAuthorization method which exists in the BaseController and which is called on each request, I tested the header of the request.
    if I requested something from the old MVC application I receive the cookies correctly enter image description here
    but when I make a request from the angular project I receive no Cookies at all

enter image description here

  1. here is how the cookies appear in chrome inspector

    for the angular project enter image description here

    and for the old MVC project enter image description here

Libbie answered 19/9, 2019 at 9:35 Comment(21)
How is that filter registered in your app?Monosaccharide
@Monosaccharide I register it globally, see my updateForeignborn
Did you performed any changes on your web.config? check sergeytihon.com/2017/01/25/…Monosaccharide
@Monosaccharide no I did not, should I apply the article exactly to my project, although I am not using Window Authorization, can you please describe in a nutshell how should I tweak the article for my specific case. thank you sir very muchForeignborn
so what cookies do you expect to be sent in your request?Monosaccharide
@Monosaccharide see the update of the questionForeignborn
can you check in the client that the cookie is set at the moment of sending the request?Monosaccharide
@Monosaccharide I am sorry I did not get exactly what you mean, can you explain to me in some details what I should do, Thank you in advancedForeignborn
I wanted to check the posibility that the cookie is not set in the browser before you make a request with angular after login in. Take a look at blinkingcaret.com/2018/07/18/… it explains some core ideas behind the cookie configuration and cross-origin requests.Monosaccharide
@Monosaccharide Thank you for the article, it really seems that It could solve my problem. I will explore it in details and let you know about that, Thank you again.Foreignborn
@Monosaccharide I added an update section to my question which describes the improvement I did from the article you gave it to me, Thank you by the way. I also start a bounty on this question, because I really need to solve this, I am stuck with it from 2 weeks. Thank you a lot for all the helpForeignborn
I check it out this article and I applied the same-site attribute of the set-cookie to none, but this still does not solve the problem. add how you did this in your updateMonosaccharide
@Monosaccharide How can I thank you I do not know. Actually I solved it immediately after updating this question. Setting the same-site attribute to none was vital but not enough, I had to add the last touch to make the magic : removing the .set('Content-Type', 'application/json') from the headers: new HttpHeaders().set('Content-Type', 'application/json')Foreignborn
@Monosaccharide please sir feel free to put an answer on this question which contains the idea of same-site attribute and the header, and I will accept it and grant the bounty for you. thank you because you saved my life, I was stuck with this from 2 weeksForeignborn
Maybe you should put Set-Cookie header inside of Access-Control-Allow-HeadersConger
@VladoPandžić Thank you problem solved, see my last 2 comments. thank you any wayForeignborn
@HakanFıstık glad to hear your problem was solved. Just to clarify; did you set the same-site property by setting the HttpCookie#SameSite property to SameSite.None? Can you confirm that by only removing the `'Content-Type', 'application/json'``header on the angular side was the problem solved? It would be interesting to understand why this would be the case. Could you provide a minimal setup of your MVC app that reproduces the issue? I would be interested in looking it in detail.Monosaccharide
@Monosaccharide HttpCookie#SameSite property exists in .NET framework 4.7.2 and above, unfortunately, my legacy project is not up to date and I am using a previous version of .NET framework, so I set this property by modifying the web.config. I used this answer https://mcmap.net/q/119068/-preventing-csrf-with-the-same-site-cookie-attributeForeignborn
@Monosaccharide really your idea is interesting, I will try just to remove the Content-type without setting the samesite property, I will try to provide the minimal setup of the project which reproduces the bugForeignborn
Try and use ngx-cookie-service to set some dummy cookie then debug in vs try and access http context in controller then check for cookie there..Rattlepate
Have you tried: newRequest = request.clone({headers: request.headers.set("withCredentials", "true")}); ?Couthie
K
2

It is not related to your ASP.NET backend, it is related to your Angular development server that is running on port 4200, while your backend server is running on port 27309. The different ports make http://localhost:4200 and http://localhost:27309 different hosts, therefore the browser doesn't attach the cookie to requests going to http://localhost:27309 despite the Angular's withCredentials: true flag.

To solve this, set up Angular's proxy configurations (a built in feature in angular) as described in this SO answer.

Kashmir answered 5/3, 2023 at 9:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.