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

Jota.Toledo
  • 27,293
  • 11
  • 59
  • 73
Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
  • How is that filter registered in your app? – Jota.Toledo Sep 19 '19 at 10:18
  • @Jota.Toledo I register it globally, see my update – Hakan Fıstık Sep 19 '19 at 10:21
  • Did you performed any changes on your web.config? check https://sergeytihon.com/2017/01/25/asp-net-mvc-with-simple-windows-authorization/ – Jota.Toledo Sep 19 '19 at 11:15
  • @Jota.Toledo 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 much – Hakan Fıstık Sep 19 '19 at 11:30
  • so what cookies do you expect to be sent in your request? – Jota.Toledo Sep 19 '19 at 11:43
  • @Jota.Toledo see the update of the question – Hakan Fıstık Sep 19 '19 at 12:16
  • can you check in the client that the cookie is set at the moment of sending the request? – Jota.Toledo Sep 19 '19 at 14:01
  • @Jota.Toledo 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 advanced – Hakan Fıstık Sep 19 '19 at 14:13
  • 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 https://www.blinkingcaret.com/2018/07/18/secure-an-asp-net-core-web-api-using-cookies/ it explains some core ideas behind the cookie configuration and cross-origin requests. – Jota.Toledo Sep 19 '19 at 14:21
  • @Jota.Toledo 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. – Hakan Fıstık Sep 20 '19 at 10:08
  • @Jota.Toledo 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 help – Hakan Fıstık Sep 22 '19 at 08:28
  • _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 update – Jota.Toledo Sep 22 '19 at 09:59
  • 1
    @Jota.Toledo 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')` – Hakan Fıstık Sep 22 '19 at 10:16
  • @Jota.Toledo 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 weeks – Hakan Fıstık Sep 22 '19 at 10:18
  • Maybe you should put Set-Cookie header inside of Access-Control-Allow-Headers – Vlado Pandžić Sep 23 '19 at 10:26
  • @VladoPandžić Thank you problem solved, see my last 2 comments. thank you any way – Hakan Fıstık Sep 23 '19 at 10:38
  • @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. – Jota.Toledo Sep 24 '19 at 07:16
  • @Jota.Toledo 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://stackoverflow.com/a/38957177/4390133 – Hakan Fıstık Sep 24 '19 at 07:47
  • @Jota.Toledo 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 bug – Hakan Fıstık Sep 24 '19 at 07:50
  • 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.. – Chetan Sharma Sep 24 '19 at 15:44
  • Have you tried: `newRequest = request.clone({headers: request.headers.set("withCredentials", "true")});` ? – Sebastian Jan 31 '20 at 15:13

1 Answers1

1

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.

Lorraine R.
  • 1,545
  • 1
  • 14
  • 39