Web API 2 security extensibility points part 4: custom authorisation filters

Introduction

In the previous post we built a custom HTTP message handler for our demo Web API 2 application. We saw how a registered message handler intercepts all calls to your API before authentication filters are executed. We also wrote a couple of examples where we checked for the presence of a custom header and of an authorisation header. We finally showed how to set the principal for the current HTTP call.

In this post we’ll see another way you can intercept the calls to your API. Authorisation filters are executed after authentication filters and before your controller action methods. That is the last stage where you can add your custom auth-related logic.

Authorisation attributes in .NET

There are built-in authorization attributes in .NET MVC and Web API. First we have the Authorize attribute which you can apply at the controller or the controller action level. You can place an empty Authorize attribute in your controllers and its effect will be that the user of the incoming HTTP call must be authenticated. This attribute has an overloaded version where you can specify a certain Role the authenticated user must be a member of, like Authorize(Role = “Admin”). You can probably guess that the user of the HTTP call must be within the Admin role in order to reach the controller or one of its actions.

You can declare that a controller or an action method can be reached with an anonymous user using the AllowAnonymous attribute.

Custom authorization filters

Just like in the case of authentication filters it’s not a major deal to construct your custom authorisation filter. All you need to is derive from the AuthorizeAttribute class and override the IsAuthorized method. It returns a boolean where a “false” means that the user is not authorised. Make sure you derive from the AuthorizeAttribute in the System.Web.Http namespace which contains many of the Web API related classes. There’s an AuthorizeAttribute class in the System.Web.Mvc namespace as well but that’s meant to be used in MVC projects instead.

As a side note we can mention the virtual HandleUnauthorizedRequest method of AuthorizeAttribute where you can carry out some custom logic in case authorization has failed.

We already have a Filters folder from part 2 of this series. Let’s add a class called CustomAuthorizationFilterAttribute to that folder with that following implementation stub. The example shows how to access the principal of the HTTP call. We’ll return false so that we can check that HandleUnauthorizedRequest is also called:

public class CustomAuthorizationFilterAttribute : AuthorizeAttribute
{
	protected override bool IsAuthorized(HttpActionContext actionContext)
	{
		IPrincipal incomingPrincipal = actionContext.RequestContext.Principal;
		Debug.WriteLine(string.Format("Principal is authenticated at the start of IsAuthorized in CustomAuthorizationFilterAttribute: {0}", incomingPrincipal.Identity.IsAuthenticated));
		return false;
	}

	protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
	{
		Debug.WriteLine("Running HandleUnauthorizedRequest in CustomAuthorizationFilterAttribute as principal is not authorized.");
                base.HandleUnauthorizedRequest(actionContext);
	}
}

You can decorate the Get action method as follows:

[CustomAuthorizationFilter]
public IHttpActionResult Get()

Run the /customers endpoint and you should see the following debug output assuming you have the auth filter and the custom HTTP message handler registered in Global.asax:

Principal is authenticated at the start of SendAsync in CustomAuthenticationMessageHandler: False
Incoming principal in custom auth filter AuthenticateAsync method is authenticated: True
Incoming principal in custom auth filter ChallengeAsync method is authenticated: True
Principal is authenticated at the start of IsAuthorized in CustomAuthorizationFilterAttribute: True
Running HandleUnauthorizedRequest in CustomAuthorizationFilterAttribute as principal is not authorized.

We can see that the Get action is never reached as the user is not authorised to access it. If you change the return statement of IsAuthorized to “return true” then everything looks good again:

Principal is authenticated at the start of SendAsync in CustomAuthenticationMessageHandler: False
Incoming principal in custom auth filter AuthenticateAsync method is authenticated: True
Incoming principal in custom auth filter ChallengeAsync method is authenticated: True
Principal is authenticated at the start of IsAuthorized in CustomAuthorizationFilterAttribute: True
Principal authenticated from extension method: True
Principal authenticated from shorthand property: True
Principal authenticated from User: True

You can set the principal in the IsAuthorized method if you want:

IPrincipal genericPrincipal = new GenericPrincipal(new GenericIdentity("Andras", "CustomIdentification"), new string[] { "Admin", "PowerUser" });
actionContext.RequestContext.Principal = genericPrincipal;

In the next post which will finish this series we’ll investigate the basics of adding an OWIN middleware to perform your authentication logic.

You can view the list of posts on Security and Cryptography here.

Advertisements

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Robin Sedlaczek's Blog

Developer on Microsoft Technologies

HarsH ReaLiTy

A Good Blog is Hard to Find

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

the software architecture

thoughts, ideas, diagrams,enterprise code, design pattern , solution designs

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Cyber Matters

Bite-size insight on Cyber Security for the not too technical.

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: