This article will explore four strategies for authorizing users who authenticate into your applications with Azure Active Directory.
We all know the two main elements of identity when it comes to App Development. There's Authentication: this is who I am; and there's Authorization: this is what I can do. Azure Active Directory does the authentication for you, but you can also use it for authorization.
In the cloud, one of the most popular systems for authentication is Azure Active Directory (AAD). If you use Office 365, when you sign in to Outlook or use the Web versions of Word or office, you are authenticating against AAD. AAD is the identity system for Office 365. If your company uses popular SAAS solutions like Salesforce, Workday, SAP or ADP and you sign in with your work Office 365 account, then you are using the same AAD to sign in to those applications. And, of course, you can build your own applications that leverages AAD to single-sign-on users with their corporate accounts. There are lots of reasons to enable SSO with AAD and thousands of SAAS providers do just that.
Let's say you're building a SAAS app. You can delegate authentication to AAD and that is well documented. But how do you authorize users? When you authenticate users from AAD using OIDC/OAUTH2, you'll get a jwt token with a globally unique identifier for that user composed of a Tenant ID (the AAD tenant the user belongs to) and an Object ID (the User's ID in that tenant). Once you have this information, you can use it to figure out what permissions (if any) the user has in your application.
For the sake of simplicity, authorization or permissions information can be put in two places. Inside AAD or somewhere else like a Bespoke Permissions system you build for your application. You can use either one or use can use both. How do you choose? There are a lot of decisions that go into designing how you authorize users. By leveraging AAD, there's fewer things you need to worry about but you may not get the granularity you need.
Here are some things to think about it when considering where to put your authorization information.
- Control: Customer has a lot control and app developer has less control.
- Management: Because your customer will be modifying objects in AAD to determine permissions, an AAD administrator may need to be actively engaged when changes are required. For example, if your SAAS application is for Marketing teams, your customer may need to submit requests to IT to change/add permissions in your system. This could add some friction.
- Licensing: if you're licensing your application per user, you'll need to be aware of how many users your customers are adding. You will need to monitor that and potentially implement a way to true-up.
- Complexity: There's less for you to build and maintain. Therefore, relying on AAD for permissions can be simpler.
- Granularity: You will use some built in AAD features. Depending on your needs this may suffice or you may need a more granular system.
- Cost: Since you're leveraging your customer's AAD, there may not be a big cost impact storing authorization information there.
- Control: Customer only has the control that the bespoke system allows.
- Management: Generally, the AAD administrator does not need to be actively involved. They will need to greenlight your app, but then the team that's actually using the application can control permissions. If you're building a SAAS app for marketing teams, the marketing team may need to ask IT to allow your application one time, but from then on they can manage permissions themselves.
- Licensing: You can more easily control how you do per user licenses because you have access to all the transactions happening in the vendor system.
- Complexity: There's more for you to build an maintain. Therefore, relying on your own system can be more complex.
- Granularity: You can build as much granularity as you need and evolve it over time.
- Cost: You will need to operate a permissions system. If you use a commercial product to manage permissions there may be a cost associated with it.
Let's look at four options for building an authorization system with AAD.
Application Roles allow app developers to define roles in their application like Administrator, Contributor, Reader. When customers add the application to AAD so they can SSO to it, the customers' AAD admins can add users to your application and assign them to roles. This is a very simple solution for you. It adds more complexity for your customers and provides the least granular set of permissions.
Permissions in your application can be aligned to custom groups in your customers' AAD tenants.
There are several ways to retrieve the group information. You can get the user's groups in the token. Or you could also ping Microsoft Graph to get the Groups the customer is a member of. There are few things to think about with groups:
- Will your customer be OK with sending information about every group a user is in?
- If you want to query Microsoft Graph to see the members of a particular group, your application will request that permission and the customer's AAD admins will have to consent to that.
- In either case, you should tell customers to create new groups that are reserved just for the roles in your applications. For example, the groups can be called "My-App Administrators", "My-App Contributors", "My-App Readers".
- You wont get the actual group names back from AAD, just their Object ID Guids. So you will need a per AAD Tenant lookup somewhere in your application to map group ids from your customers' tenants.
Which should you choose? There's a discussion about Roles vs Groups here: https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-add-app-roles-in-azure-ad-apps#app-roles-vs-groups
Here's a Microsoft Learn course to get hands on with groups and roles: https://docs.microsoft.com/en-us/learn/modules/identity-users-groups-approles/
AAD gives you couple of options for integrating with a Bespoke permissions system.
You may want to use this, rather than AAD, if you need more granular or advanced authorization features like ACLs, Policies and RBAC.
You can add authentication with AAD into your application directly in your code. You can use the MSAL library to integrate AAD. You can also use a service that acts as a proxy to many identification providers. Let's say you have customers that use AAD and customers that use Google Workspace. There are various Identity Services out there that will make it easy for you to talk to many identity providers. Microsoft's offering for this Azure AD B2C.
During the authentication flow, Azure AD B2C can call out to a 3rd party API to get custom claims. You can build that 3rd party API around your Bespoke Permissions system. B2C can call that API and merge claims from your Bespoke Permissions service into the JWT token it returns to your application. The benefit of this approach is that your application only calls one service, Azure AD B2C and it gets back a consistent set of claims. Azure AD B2C does the hard-work of calling multiple identity providers and 3rd party permissions services.
If you have a Bespoke Permissions system and expose it as an API, you can have your application call it directly. You can leverage AAD to make sure calls to the permissions API service are protected. In this case, you're using your own AAD, not your customers. It just takes a few steps to make this work.
- In AAD you'll give your application an identity.
- In AAD you'll give your permissions service API an identity.
- In AAD, you'll configure the permissions service API to allow the application to make requests to it.
- In your application, when you make requests to the permissions service, you'll present the identity, so the permissions service knows who's calling and will allow it.
There are other ways to implement authorization and permissions in your application. In this article I discussed four strategies that leverage AAD. There are lot of elements to consider when deciding which strategy to choose. If using roles and groups inside of AAD is not granular enough there are many 3rd party authorization systems that you can integrate into your application, including open source projects like Casbin. I hope you found this discussion useful!