XSRF Token validation fails in ASP.NET Core with separate machine to serve Angular

1k Views Asked by At

I am working on a dotnet core API 6.0 with separate machine to serve Angular 13 application.

I am trying to secure my application with CSRF-Token. I am setting XSRF-TOKEN cookie from C# and withCredentials as true in Angular app, also sending header X-XSRF-TOKEN with same value as we have for XSRF-TOKEN cookie.

Added below code but its failing xsrf token validation when I hit any api endpoint with X-XSRF-TOKEN header in my request and returning 400.

Startup.cs > ConfigureServices Method

services.AddAntiforgery(options =>
            {
                options.HeaderName = "X-XSRF-TOKEN";
            }); //Preventing Cross-Site Request Forgery (XSRF/CSRF) Attacks in ASP.NET Core
            services.AddMvc(o =>
            {
                o.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); // adding auto validation of Antiforgery Token.
            });

Startup.cs > Configure Method

 app.Use(next => context =>
            {
                string path = context.Request.Path.Value;
                if (path != null && path.ToLower().Contains("/api"))
                {
                    var tokens = antiforgery.GetAndStoreTokens(context);

                    context.Response.Cookies.Append(appSettings.XSRFCookieName, tokens.RequestToken,
                    new CookieOptions()
                    {
                        //Path = "/",
                        SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None,
                        HttpOnly = false, // a special kind of cookie that’s only sent in HTTP requests to the server, and it’s never accessible (both for reading or writing) from JavaScript running in the browser. 
                        Secure = true, // true is used to send cookie to browser otherwise it would not be sent to browser //env.IsDevelopment() ? false : true, // if true, means it can be sent over https(SSL) only.
                        IsEssential = true,
                        Expires = DateTime.UtcNow.AddMinutes(appSettings.JwtSettings.MinutesToExpiration),
                    });
                }

                return next(context);
            });

Angular

@Injectable()
export class JwtInterceptor implements HttpInterceptor {
  constructor(private authenticationService: AuthenticationService, private tokenExtractor: HttpXsrfTokenExtractor) {}

  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
  const xsrfToken = this.tokenExtractor.getToken() as string; 
  const AllowCredentialsVal = true;
  var headers = new HttpHeaders({
        //Authorization: `Bearer ${currentUser.jwtToken}`,
        'X-XSRF-TOKEN': xsrfToken, //can be handled in app.module to auto set this header using browser cookie when both API and Agular app are on same server with cookie options as Path = / and httpOnly = false.
        //'RequestVerificationToken': xsrfToken,
        'Access-Control-Allow-Origin': GlobalConstants.BASE_API_URL, // Website you wish to allow to connect
        'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, PATCH, DELETE', // Request methods you wish to allow
        'Access-Control-Allow-Headers': 'X-Requested-With,content-type', // Request headers you wish to allow
        'Access-Control-Allow-Credentials': `${AllowCredentialsVal}`, // Set to true if you need the website to include cookies in the requests sent to the API
      });
    request = request.clone({      
      headers,
      withCredentials: AllowCredentialsVal,
    });
   // Pass to next layer of middleware
    return next.handle(request);
  }

Below are request header and cookies from browser's network tab, X-XSRF-TOKEN header and XSRF-TOKEN cookie has same value. Not sure what is missing, can someone please help, TIA. a5 enter image description here

0

There are 0 best solutions below