3

I am trying to secure my application with CSRF-Token, therefore I used Angular docs. They state, that if in Cookies you have a cookie named XSRF-TOKEN, then this cookie will be automatically provided to backend in Headers, which indeed is true. Everytime I make a POST request from my Angular Frontend App, the cookie is put in Headers(as X-XSRF-TOKEN). Therefore, I changed the default Anti Forgery Token Cookie name to XSRF-TOKEN in ASP .NET Core:

// Startup.cs
services.AddAntiforgery(options =>
{
    options.HeaderName = "X-XSRF-TOKEN";
    options.Cookie = new CookieBuilder()
    {
        Name = "XSRF-TOKEN"
    };
});

I have also provided the token attribute as a filter in the request stream:

services.AddControllers(opt =>
{
    opt.Filters.Add(typeof(LoadFilter), Int32.MinValue); // my other custom filter
    opt.Filters.Add<AutoValidateAntiforgeryTokenAttribute>();
})

There is also the middleware that takes care of storing the token in cookies and validates it when a POST request comes:

    public class ValidateAntiForgeryTokenMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IAntiforgery _antiForgery;

        public ValidateAntiForgeryTokenMiddleware(RequestDelegate next, IAntiforgery antiForgery)
        {
            _next = next;
            _antiForgery = antiForgery;
        }

        public async Task Invoke(HttpContext context)
        {
            if (HttpMethods.IsGet(context.Request.Method))
            {
                _antiForgery.GetAndStoreTokens(context);
            }
                
            if (HttpMethods.IsPost(context.Request.Method))
            {
                await _antiForgery.ValidateRequestAsync(context);
            }
            await _next(context);
        }
    }

    public static class ApplicationBuilderExtensions
    {
        public static IApplicationBuilder UseAntiForgeryTokens(this IApplicationBuilder app)
        {
            return app.UseMiddleware<ValidateAntiForgeryTokenMiddleware>();
        }
    }

Now, whenever I make a GET request to the backend server, an XSRF-TOKEN cookie is being set. However, when I make a POST request with XSRF-TOKEN cookie and X-XSRF-TOKEN header with the same value, I get errors. First error, on my local development machine:

Antiforgery token validation failed. Validation of the provided antiforgery token failed. The cookie token and the request token were swapped

Second error, on my dev server, which produces another error, even though the code is the same:

The required antiforgery cookie ".AspNetCore.Antiforgery.6zP9GDvCs-o" is not present.

Also, if I manually add the cookie in ValidateAntiForgeryTokenMiddleware, everything seems to work correctly. But then, I have two XSRF-TOKENS, which doesn't seem a good solution, because it puts the security aspects in two other places, when I think one cookie should be enough.

1 Answer 1

1

Add Interceptor in angular side. Make sure to add withCredentials: true in each request.

http-xsrf-interceptor.ts

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

@Injectable()
export class XsrfInterceptor implements HttpInterceptor {
constructor(private tokenExtractor: HttpXsrfTokenExtractor) { }

intercept(req: HttpRequest<any>, next: HttpHandler): 
Observable<HttpEvent<any>> {
    req = req.clone({ withCredentials: true });
    const headerName = 'X-XSRF-TOKEN';
    const token = this.tokenExtractor.getToken() as string;
    if (token !== null) {
        req = req.clone({ headers: req.headers.set(headerName, token) });
    }
    return next.handle(req);
  }
}

app.module.ts - in provider section.

   {
        provide: HTTP_INTERCEPTORS,
        useClass: XsrfInterceptor,
        multi: true
    },
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.