Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement custom ValidateAntiforgeryTokenAuthorizationFilter in ASP.NET Core 3.1

I'd like to implement a filter that skips validation of an antiforgery token when an auth token authentication (Bearer) is used.

In the ASP.NET Core 2.2 the ValidateAntiforgeryTokenAuthorizationFilter and AutoValidateAntiforgeryTokenAuthorizationFilter were public (even though living in the Microsoft.AspNetCore.Mvc.ViewFeatures.Internal namespace), so I was able to just inherit from the latter and override the ShouldValidate method easily.

In the ASP.NET Core 3.0 they became internal, so it's not possible to just inherit from them. I can just copy-paste the code, but it's not the ideal solution obviously.

I was following the Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core article from MSDN, but it doesn't really mention anything relevant to my scenario.

like image 893
Grzegorz Smulko Avatar asked Dec 31 '19 15:12

Grzegorz Smulko


People also ask

What is AntiForgeryToken in asp net core?

In ASP.NET Core, @Html. AntiForgeryToken() is applied for preventing cross-site request forgery (XSRF/CSRF) attacks.

What does Antiforgery validate do?

Validates that input data from an HTML form field comes from the user who submitted the data and lets callers specify additional validation details.

How ValidateAntiForgeryToken works in MVC?

MVC's anti-forgery support writes a unique value to an HTTP-only cookie and then the same value is written to the form. When the page is submitted, an error is raised if the cookie value doesn't match the form value. It's important to note that the feature prevents cross site request forgeries.

What is a XSRF token cookie?

Cross-site request forgery, also known as one-click attack or session riding and abbreviated as CSRF (sometimes pronounced sea-surf) or XSRF, is a type of malicious exploit of a website or web application where unauthorized commands are submitted from a user that the web application trusts.


1 Answers

Normally you can use [IgnoreAntiforgeryToken] attribute if you can determine at compile-time that the csrf token should be ignored. If you want such an ability at run-time, you could create a custom FilterProvider that will provide an IAntiforgeryPolicy if there's a Authroization: Bearer json-web-token header.

For example, we can create a custom AutoSkipAntiforgeryFilterProvider as below:

public class AutoSkipAntiforgeryFilterProvider: IFilterProvider
{
    private const string BEARER_STRING = "Bearer";
    public int Order => 999;
    public void OnProvidersExecuted(FilterProviderContext context) { }
    public void OnProvidersExecuting(FilterProviderContext context)
    {
        if (context == null) { throw new ArgumentNullException(nameof(context)); }
        if (context.ActionContext.ActionDescriptor.FilterDescriptors != null)
        {
            var headers = context.ActionContext.HttpContext.Request.Headers;
            if (headers.ContainsKey("Authorization"))
            {
                var header = headers["Authorization"].FirstOrDefault();
                if(header.StartsWith(BEARER_STRING,StringComparison.OrdinalIgnoreCase))
                {
                    var FilterDescriptor = new FilterDescriptor(SkipAntiforgeryPolicy.Instance, FilterScope.Last);
                    var filterItem = new FilterItem( FilterDescriptor,SkipAntiforgeryPolicy.Instance);
                    context.Results.Add(filterItem);
                }
            }
        }
    }

    // a dummy IAntiforgeryPolicy
    class SkipAntiforgeryPolicy : IAntiforgeryPolicy, IAsyncAuthorizationFilter
    {
        // a singleton 
        public static SkipAntiforgeryPolicy Instance = new SkipAntiforgeryPolicy();
        public Task OnAuthorizationAsync(AuthorizationFilterContext context) => Task.CompletedTask;
    }
}

And register this filter provider in Startup :

services.TryAddEnumerable( ServiceDescriptor.Singleton<IFilterProvider, AutoSkipAntiforgeryFilterProvider>());

Now it will bypass the AntiForgery even there's a [ValidateAntiForgeryToken]attribute.


[Demo]

Assume we have an action method annotated with [ValidateAntiForgeryToken]:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name")] XModel xModel)
{
    ....
}

Normally, it will protect this method with CSRF token. But if you send a request like:

POST /XModels/Create HTTP/1.1
Authorization: Bearer Xyz 
Content-Type: application/x-www-form-urlencoded

...

it won't validate the csrf token.

like image 169
itminus Avatar answered Oct 08 '22 09:10

itminus