ASP.NET Web API in Azure: configure an authentication filter to prevent brute force?

I have a website from the SPA VS2013 template (web api 2.2) that uses ASP.NET Identity 2.1 and everything works very well. My controller methods look like this:

    [Authorize]
    public Api.Models.Widget Get(int widgetId)
    {
    var requestingUserId = Int32.Parse(Microsoft.AspNet.Identity.IdentityExtensions.GetUserId(User.Identity));
    ...

}

      

Works as expected:

  • Unauthorized users are denied access
  • After the logged in user is logged in, I can get the user id

But Now I want to modify the application to prevent excessive API requests. I am planning to check if this specific user id has actually made a certain number of requests during a certain timeframe. I am looking for suggestions for the best location for this.

I wouldn't want to repeat this logic in every controller, and it seems like an action filter might be a better place. But since this will need to read the user id, and I'm not sure if the order of the filters is guaranteed, it might make sense, if possible, to get the filter that has already been called for authorization and add my additional logic.

I am wondering if anyone can provide an example of what needs to be done? It looks like instead of "authorizing" it would be in a custom authentication filter and I'm not sure how to tie this together.

Thanks for any suggestions ...

+3


source to share


2 answers


There are several filtering options:

Authorization Filter Makes decisions about whether to execute an action method, such as authenticating or checking request properties.

Example:

public class WebApiAuthorizeAttribute : AuthorizeAttribute 
{
    public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        base.OnAuthorization(actionContext);

        Guid userId = new Guid(HttpContext.Current.User.Identity.GetUserId());

        // ...here your validation logic 
    }
}

      

Action Filter Flows around the execution of an action method. This filter can perform additional processing, such as providing additional data for the action method, validating the return value, or canceling the execution of the action method.



To minimize the impact on your server, you can cache any HTTP request in the user's browser for a predefined time, if the user requests the same URL at that predefined time, the response will be loaded from the browser cache, not the server. Since the OutputCache attribute is not available for Web APIs, you can use this ASP.NET Web API output caching as an alternative, or you can implement your own Action Filter Attribute for caching:

public class CacheFilterAttribute : ActionFilterAttribute
{
    /// <summary>
    /// Gets or sets the cache duration in seconds. The default is 10 seconds.
    /// </summary>
    /// <value>The cache duration in seconds.</value>
    public int Duration
    {
        get;
        set;
    }

    public CacheFilterAttribute()
    {
        Duration = 10;
    }

    public override void OnActionExecuted(FilterExecutedContext filterContext)
    {
        if (Duration <= 0) return;

        HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
        TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);

        cache.SetCacheability(HttpCacheability.Public);
        cache.SetExpires(DateTime.Now.Add(cacheDuration));
        cache.SetMaxAge(cacheDuration);
        cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
    }
}

      

Additional considerations

Once a user makes a call against your web avi, you will need to add +1 to the counter and then use that counter to check for bulk calls with the same user in the timeframe. The problem here is where to store this counter.

If you store the counter in a DBMS like SQL Server, each user call will access the DB. This can be a performance issue. This storage should be as light as possible. So using NoSQL db might be a good approach.

+1


source


I think you care about the filter that will throttle the requests made by your users, so you should check out WebApiThrottle https://github.com/stefanprodan/WebApiThrottle



This should do what you intend to do, or you can check out the source code to customize it for your four needs.

+4


source







All Articles