Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where should I plugin the Authorization in Asp.net WebAPI?

Tags:

As I see I have 3 possible places to plug my stuff in the pipeline

1)     AuthorizationFilters  2)     Action Filters  3)     DelegatingHandler 

The most obvious one is AuthorizationFilters , where I can decorate my actions/ controllers with my custom authorization attribute . say .. MyCustomAuthorizationAttribute .

Since HTTP message handlers are in the first stage in the processing pipeline. Does it make any sense to put it in there ?

Authorization for me right now simply means checking a token in the header which is given to the client after authentication.

like image 512
ashutosh raina Avatar asked Feb 14 '13 09:02

ashutosh raina


People also ask

Where can the Authorize attribute can be applied?

You can place the Authorize attribute on a controller or on individual actions inside the controller. When we place the Authorize attribute on the controller itself, the authorize attribute applies to all of the actions inside.

How will you implement authentication and authorization in ASP.NET Web API?

Web API assumes that authentication happens in the host. For web-hosting, the host is IIS, which uses HTTP modules for authentication. You can configure your project to use any of the authentication modules built in to IIS or ASP.NET, or write your own HTTP module to perform custom authentication.

How do I Authorize API?

When your application requests private data, the request must be authorized by an authenticated user who has access to that data. When your application requests public data, the request doesn't need to be authorized, but does need to be accompanied by an identifier, such as an API key.


1 Answers

Update July 2014

My original answer covered WebApi 1. with WebApi 2 there were some changes i.e. there is now an IAuthenticationFilter meaning you can move authentication logic out of the DelegatingHandler which is a little more elegant.

There is a Nuget project here that offers an implementation of IAuthenticationFilter and also explains some background to its introduction.

OWIN middleware is now perhaps the best place to implement your authentication logic - there is an example of Certificate Authentication here and Basic Authentication OWIN Middleware here in this blog post the former example is the preferred one as it demonstrates the use of the base AuthenticationHandler class.

The advice on AuthorizationFilters remains largely unchanged.

End Update

Typically...

Use DelegatingHandler to carry out Authentication... i.e. who someone is. Use this to set the Principle of the Thread and User context, add claims etc. You can place authorisation logic here too but on a fairly global scale. I would personally always use AuthorizationFilters for authorisation.

Use AuthorizationFilters to restrict controllers and actions to specific people. These are used when you can extrapolate their permission with the information in claims, principal, url or the http request parameters. The default authorisation filter can be used to restrict access to anonymous users or by roles (if set in something like a delegating handler) - obviously you can implement your own AuthorizationFilters too if you need it.

Occasionally use ActionFilters when you need to make the decision over authorisation using the message content e.g. you need access to a property on the entity to decide whether they have access (obviously be careful with this(!)).

Note:

The AuthorizationFilters are called before the content of the body is read therefore they do not have access to the message body to make authorization decisions this is why the ActionFilters specifically the OnActionExecuting is used to occasional raise authentication errors.

So

In your scenario I would put a simple DelegatingHandler to take your header and set the principal.

public class CustomAuthenticationMessageHandler : DelegatingHandler {       public CustomAuthenticationMessageHandler ()     {      }      protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,                                                            CancellationToken cancellationToken)     {         Authenticate(request);          return base.SendAsync(request, cancellationToken);     }      protected virtual void Authenticate(HttpRequestMessage request)     {          var authorisationHeader = request.Headers.Authorization;          if (authorisationHeader == null)         {             return;         }          //Ensure you are happy with the header contents then          {             var principal = new GenericPrincipal(//new Identity , //Roles);             Thread.CurrentPrincipal = principal;             HttpContext.Current.User = principal;         }      } } 

Then use AuthorizationFilters to restrict access:

    [Authorize]     public string Get()     {      }      [Authorize(Roles = "Admin")]     public string GetAdminOnly()     {      } 

To register the global Authentication

config.MessageHandlers.Add(new CustomAuthenticationMessageHandler()); 

This will mean that in every request the principal will be set to either null or a valid identity. It won't handle authorisation i.e. wont deny access to any controllers or actions.

To start protecting resources

Either target protected controllers and actions with the standard or custom [Authorize] attributes. Or register globally:

config.Filters.Add(new AuthorizeAttribute()); 

And only white list the controllers and actions you want unsecured using the [AllowAnonymous] attribute.

If you only want authentication on some routes

Then you can modify your DelegatingHandler a little to set the InnerHandler to route to the correct controller e.g.

public CustomAuthenticationMessageHandler(HttpConfiguration configuration) {        InnerHandler = new HttpRoutingDispatcher(configuration); } 

And then you can specify this handler on your routes like so:

config.Routes.MapHttpRoute(             name: "DefaultApi",             routeTemplate: "myurl",             defaults: new {},             constraints: new {},             handler: new CustomAuthenticationHandler(config)             ); 
like image 138
Mark Jones Avatar answered Sep 20 '22 16:09

Mark Jones