Image for post
Image for post
Photo by Bekky Bekks on Unsplash

Role based authorization in Azure Functions with Azure AD and app roles

How to limit access to restful APIs in Azure Functions with .NET Core by assigning users to app roles in Azure Active Directory

Philipp Bauknecht
Jun 14, 2020 · 4 min read

In this previous post I discussed how to authenticate users in Azure Functions using Authentication/Authorization (formerly know as Easy Auth): https://medium.com/medialesson/protecting-azure-function-apps-with-azure-ad-authentication-authorization-fd167ce4fe33

Authenticating users in a backend API built with .NET Core and running in Azure Functions is usually just the first step to control and limit access to resources and features to certain users or groups. Now that we know who the user is we need to decide whether to allow access to a resource based on app roles.

One important drawback to consider: app roles are created individually per app registration. This means that in typical client server situations where we have a client (e.g. Angular) and a server/backend (e.g. Azure Functions) this means we need to create app roles in both app registrations and also manage user assignments for both separately. This can be mitigated by assigning app roles to security groups but this feature is limited to Azure AD premium tenants and so not available if an organization is using the Azure AD that comes with Microsoft 365.
Read more about app roles and other options for authorization here: https://docs.microsoft.com/de-de/azure/architecture/multitenant-identity/app-roles

Setup an app role

App roles are created in the app registration’s manifest and users can be assigned those roles. So let’s open our Azure Function app registration’s manifest in the Azure portal and add a role:

Image for post
Image for post

Note that each role needs a unique id and the value property is the value that will be included in the user’s claims.

Assign users to an app role

To assign users open the app registration by opening it via Enterprise applications instead of App registrations:

Image for post
Image for post

Switch to Users and groups, select Add user, search for a user and click assign:

Image for post
Image for post

Limit function to a role

With app roles configured and at least one users assigned it’s time to turn to Azure Functions. Let’s start with the project we created in the previous post: https://medium.com/medialesson/protecting-azure-function-apps-with-azure-ad-authentication-authorization-fd167ce4fe33

The logged in user’s assigned roles are part of the claims in the access token used for a request. So we can pull them from the ClaimsPrincipal object:

Note how we add the ClaimsPrincipal parameter to the function’s method. Each assigned role will be in a claim with the type “roles”.

Checking the user’s roles in each function method would be pretty repetitive though. A better approach is to create some form of middleware that checks the user’s roles before entering a function method. This middleware needs to be configurable so each function can decide which role it requires. To implement this requirement a possible way is to write a custom RoleAuthorizeAttribute that derives from FunctionInvocationFilterAttribute.

This attribute class needs to have a constructor parameter to allow to specify which role(s) are required for a function using the attribute.

The params keyword in the construction allows to pass in one or more role values. The method OnExecutingAsync gets called before a function method is executed when the attribute is used like this:

Important: Don’t remove the ClainsPrincipal parameter from the function as this defines which properties are passed into the arguments of the FunctionExecutionContext parameter in the attribute’s OnExecutingAsync method.

Now that the attribute is created and wired with a first function let’s implement the OnExecutingAsync method to decide whether to continue with the function executing based on the roles:

Note that there is a custom exception AuthorizationException that is being thrown when either claims are missing or the user’s roles in the claim don’t match the valid roles. The reason for throwing an exception is that I have yet to find another way of stopping the function’s method to execute and return a useful http status code result like in this case a 401.

So my approach is to a) throw a custom exception and the b) have the function’s class implement the IFunctionExceptionFilter interface. This interface allows to intercept exceptions and return http results. Like with the RoleAuthorizeAttribute we don’t want to implement this interface every time we need to use roles so let’s create a base class for all functions using roles:

To write a response this base class needs to have a IHttpContextAccessor injected in the constructor. Then we can filter for our custom AuthorizedException and return our 401 response.

Finally our function’s class needs to derive from BaseAuthorizedFunction. As we need to pass through the IHttpContextAccessor in the constructor we need to make the function’s class and method non static:

Summary

With this setup we have a reusable solution to limit execution of HttpTrigger functions (aka http apis) to not only authenticated users but also authorize based on the user’s assigned app roles. This works both in typical line of business as well as SaaS scenarios.

medialesson

We help our customers design, architect, develop and…

Philipp Bauknecht

Written by

CEO @ medialesson. Microsoft Regional Director & MVP Windows Development. Father of identical twins. Passionate about great User Interfaces, NYC & Steaks

medialesson

We help our customers design, architect, develop and operate modern, intelligent, beautiful and usable apps on any platform powered by the Cloud, IoT and AI.

Philipp Bauknecht

Written by

CEO @ medialesson. Microsoft Regional Director & MVP Windows Development. Father of identical twins. Passionate about great User Interfaces, NYC & Steaks

medialesson

We help our customers design, architect, develop and operate modern, intelligent, beautiful and usable apps on any platform powered by the Cloud, IoT and AI.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store