Tag Archives: RBAC

General Roles-Based Access Control in the .NET backend

Lately, I’ve received a lot of questions related to roles-based access control (RBAC). It’s a great, clean way to define which users have which permissions, where a user is assigned to one or many “roles,” and your resources are protected by specifying which roles are allowed to access them. I recently wrote a post on basic RBAC for AAD using the Node.js backend, but today I’ll tackle a more generalized case, and I’ll do it using the new .NET backend preview.

Let’s assume I’m building a simple consumer forums application, in which I want an option to mark posts as “sticky.” This means it will always appear at the top of the posts list. My forum would likely end up in a bad state if I let all users do this, so I want to restrict the action to moderators only. All of my users will be authenticated via Facebook, and I’ll be keeping track of their roles (moderator or not) within a database table in my application.

So the question arises: how do I make it so that only moderators can mark a post as “sticky?”

To start things off, let’s take a look at the target programming model. I’ll be working with a ForumPost object and its associated controller. Since we’re making a change to an existing post we’ll be protecting the HTTP PATCH method. Here’s the controller, with just the PATCH method:

Looks nice and simple, right? We just decorate the method with an attribute specifying the allowed roles. It’s pretty similar to the AuthorizeLevel attribute that Mobile Services provides by default with the .NET backend. In fact, we’ll be replicating a bit of that attribute’s functionality as we go through this process.

Creating a custom authorization attribute

So first, let’s address the creation of an attribute. The basic premise is that you need to derive from the abstract class Attribute. In our case, we’ll be using the concrete subclass AuthorizationFilterAttribute, which will make things a bit simpler for us. There are basically two parts needed here: a constructor which turns the annotation into usable data, and an OnAuthorization() method which will get called when a user attempts to access the endpoint.

As you can see, I’m actually accepting an arbitrary number of roles, which would be separated by commas in the annotation. I’m then storing these in a HashSet for easy lookup when we get to OnAuthorization(). Everything is being handled as strings here, but you could certainly work with enums, which would make the experience a little cleaner when you go to protect your endpoints.

The other important thing to note is the AttributeUsage section, where I’ve said that the attribute can decorate both full controllers or just individual methods. Also, since I accept a variable number of arguments, I’ve gone ahead and restricted developers to using one instance of this attribute per method/controller.

Authorizing the user

Now we can focus on the OnAuthorization() method, which is where we will make the decision about whether or not the decorated method/controller can be accessed. We need to get a notion of the currently logged-in user and their roles, so first we need to make sure that someone is actually logged in. In doing so, we’re technically replicating the behavior of AuthorizeLevel attribute, as if we’ve set the value to “User.” After we’ve cleared that hurdle, we can check for roles.

One option is to, if applicable, use the associated identity provider’s graph. However, many cases will look similar to today’s scenario, where the role is completely application-level, perhaps stored in the database. You can see that I’m just querying my table to get the roles held by the user. Regardless of what method you choose, once you have your roles, you can just cross-check against the list specified by the attribute.

And that’s pretty much all you need to do! Just place this class in a location accessible to your backend project, and you have all you need to get started protecting your APIs at fine granularity. The approach should work across identity providers – in fact, you may have noticed that while I mentioned Facebook in the scenario description, nowhere in my code did I care where the user came from.

As a next step for the enterprise-inclined: you can take my post on RBAC with AAD (in Node) and combine those concepts with this solution pretty easily. I should hopefully have a post out soon covering more of the cool things you can do with AAD and the .NET backend, so keep an eye out for that.

Resources

Mobile Services Forums – In keeping with today’s theme, and because it’s a great place to turn if you have questions about anything Mobile Services.
Mobile Services UserVoice – While we’re at it, we’re always looking for feedback, so please make yourself heard here!
Getting Started with the .NET backend – There’s a lot of cool new things you can do with the new .NET backend. It should feel familiar to ASP.NET WebAPI developers, but even if you’re new to that stack, it’s easy to get started. Try it out!
Getting Started with Authentication in the .NET Backend – This shows you how to work with social providers. For AAD, see below.
Getting started with AAD in the .NET Backend – AAD for the .NET runtime is only available via a client flow right now. This tutorial will get you started.

Roles-Based Access Control in Mobile Services and Azure Active Directory

This post originally appeared on the Azure blog on 3/11/2014. I am posting it again here for convenience.

In November, we announced a preview of Azure Active Directory (AAD) as an identity provider for Mobile Services. The mission was to give enterprise developers an easy solution for building employee-facing mobile apps. Basic authentication is a great start, but in many cases our current preview customers have needed to distinguish between types of users in order to make authorization decisions. Roles-based access control (RBAC) is the idea of assigning permissions to roles that your users can hold, nicely defining boundaries on what certain classes of users can and cannot do. Luckily, it is very easy to add basic RBAC to Azure Mobile Services, and this post will walk you through how to accomplish that.

In order to follow along with the rest of this post, you’ll need to be enrolled in the Mobile Services preview for Azure Active Directory integration. If you would like access, please email MobileServices@microsoft.com.

Background

Let’s imagine that I want to develop an application just for my sales team. In order to access the app, a user not only has to be a member of my company’s directory, but also assigned to the sales group.  Let’s take a look at the logic you’d need to add on the server-side to ensure that only authenticated members of the sales team can access the app. (If you’re just getting started with Azure Active Directory Authentication in Mobile Services, you may find this getting started tutorial helpful.)

The basic approach we’ll be taking is to leverage security group membership for users in our Azure AD tenant. AAD has the concepts of both roles and groups, but in today’s scenario we’re working with an existing group that already has the correct user membership. We’ll be managing our group from an on-premises AD tenant that is synced with our Azure AD tenant. Customers of O365 and Windows Intune can attest that you get a lot of power by setting up a directory sync with on-premises Active Directory (and you can even use those tenants to build Mobile Services).

RBAC_1

Today, I’m going to be using the “Password Sync” option, but there are multiple scenarios supported. You can actually set up AAD to point to ADFS for a great hybrid scenario. If you want to play with these options, spin up an Azure VM running Windows Server 2012 R2 Datacenter and install the Active Directory Domain Services role. Then follow the directory sync instructions.

Creating Groups

Within my directory, you can see that I’ve created some users (Alice, Bob, Carol, and Dave) as well as a “Sales” domain security group. I’ve made Alice and Bob members of this group, but Carol and Dave remain outside it and should not have access to my app. Everything else is default.

RBAC_2

Connecting to Azure Mobile Services

So I’m now ready to start building my app backend. In an Azure mobile service, we want to protect each of our scripts and APIs with additional authorization logic on top of what is provided. For some extra sanity, I’m going ahead and setting permissions to “Only Authenticated Users” for each protected endpoint.

RBAC_3

Because I’m building logic that I want executed in multiple scripts, I’m putting my code in the shared scripts section of my mobile service’s Git repository. I’m naming the script rbac.js.

The first step to determining group membership is to gain access to the AAD graph API. Setting this up is covered in this blog post as well as in this sample. The following will get you started:

Once we have the graph access token, we need to call the isMemberOf graph endpoint. This will check if the specified user is a member of a given group, including transitive membership. We can get the user ID from the script being checked – all table scripts explicitly receive a user object, and you can get one from a Custom API by accessing request.user. We’ll need to obtain a group ID, which is conveniently available in the management portal. Head into your Azure AD tenant, open the groups tab, select the group, and copy the Object ID from under the configure tab.

RBAC_4

For ease of use, we’ll export the value from our shared script with a friendly name.

We’ll now want to write a function to wrap our call to the AAD isMemberOf endpoint. As mentioned before, we’ll need both the userID and the groupID we just obtained. The request also needs to include the access token that we obtained.

We’ll simplify the programming model a bit and just require the Mobile Services user object (from which we can get the objectID), as well as the group ID. We’ll wrap it up nicely to get the graph token for us and make the call. Note that in production, you’ll really want to cache this token instead of fetching it every time. The token contains an expiration value that you can use to determine when you should fetch a new one.

That’s all for the shared script. Now, for each script that I want to protect with RBAC, I just have to add a few lines and perform the script’s work in my callback. Here’s an example for a table read:

Wrapping Up

And that’s it. We’ve successfully restricted our app usage to the subset of our employees that needs it. From here, you can start building for a variety of RBAC scenarios. If you find that you want to differentiate the client UI for certain users, one simple way to do this is to expose the membership check as a Custom API, which you can invoke immediately after login.

Azure Active Directory is doing some cool things with their group support, and a lot can be accomplished straight from the management portal. AAD Premium users should be sure to check out the new self-service group management support.

If you are interested in enterprise mobile app development, I encourage you to also check out the new Mobile Services .NET backend preview. It does not currently have built-in AAD support, but don’t worry! We will have it available soon.

And again, if you’re interested in joining the AAD preview or have any questions, please reach out to us at mobileservices@microsoft.com.

If there are additional features or scenarios you’d like to see covered, please submit your feedback to our uservoice.