Difference between an application role and scope in Azure AD app registrations - azure

I have created an API that is protected by OAuth using an app registration in Azure.
My app registration does not require assignment, but it exposes a number of roles that the underlying API verifies. To my understanding, this accomplishes almost the same thing as requiring approval.
So far I've only had user/group roles but now I've added an application role intended for integrators, and I want other application owners to be able to request permission to my API. I, as the API owner, would like to review these and either reject or consent to the request. E.g. I don't want everyone to be able to access my API within the tenant without my knowledge, just like all users/groups don't have access with me assigning them to a role.
The Role-based access control for application developers documentation makes it very clear who manages access:
...an application developer defines roles rather than authorizing individual users or groups. An administrator can then assign roles to different users and groups to control who has access to content and functionality.
However, if you create a role with allowed member types set to application, things are not quite as clear and it seems to behave more like a scope, where I give up any access management. Also from my limited understanding, a scope is used when the API needs to request data from the user (e.g. wanting to read their username), whereas a role is used for the application developer to control access to what they are developing.
This is what it looks like when I request access to my API from another app:
This same page mentions the following information:
The "Admin consent required" column shows the default value for an organization. However, user consent can be customized per permission, user, or app. This column may not reflect the value in your organization, or in organizations where this app will be used.
As well as:
Applications are authorized to call APIs when they are granted permissions by users/admins as part of the consent process
However, from my reading, it sounds like this never gives me, as the API owner, any insight into who has access to the API I own. I want to control application access the same way I'd assign a group or user to a role in the enterprise application.
Can this be achieved when it's an application on the other end, not a user? If not, how would I allow applications to integrate in a controlled manner?

I want to explain the feature Azure ad provided to protect web api here.
As you know, we usually use a token in the request header to let the api check if the request had correct permission to visit the api. Such as if the request from an allowed user role, right? So to whole progress should be authentication and authorization. Users sign in first then try to generate an access token to visit an api. Azure AD has similar architecture.
If you had a web application(e.g. web mvc app) you can integrate Azure AD into it then you can allow users use their user1#xx.onmicrosoft.com account to sign in. If you had a web api project, you can also integrate Azure ad and add [Authorize] attribute above the controller so that the incoming request should contain a correct Bearer token which we call it access token.
For Azure AD, we usually have 2 options, verification scopes or app roles. That results from the different flows we used to generate the access token. For example, we use auth code flow to sign in users and generate access token containing scp claim which is granted delegated api permissions. And we use client credential flow to let an application to generate access token containg roles claim which representing it's granted application api permissions. In short, when we set [Authorize] + [RequiredScope(scopeRequiredByApi)] in the controller, it allows requests from a user(user sign in the app and call api), when we set [Authorize(Roles = "roleRequiredByApi")], it allows requests from the application(no user signed in and the app call api by itself).
Here scopeRequiredByApi and roleRequiredByApi is what you exposed and then added to App Registration > Permissions. Just like Integrator you marked in the screenshot, it can be recognized as roleRequiredByApi because its type is Application.
And I'm afraid the roles is not what you want but to be honest what I said is what AAD can do for you... And I think the document I mentioned above about verification scopes or app roles will be a good sample for you.

The App Registration > Permissions section has a great feature for reviewing and limiting the access provided for your app registration:
enter link description here
In addition you should always define the scope of your permissions and limit it to the least required for your app. eg. NEVER set scope at the subscription level! Always set it at the resource group or lower.
Also note that Microsoft now provides Defender for APIs and you can use Sentinel to monitor a lot of the activities related to your app registration. Always always enable logging wherever possible and configure some method of alerting/reporting so you can better understand the activities for your app.

Related

Custom Application permissions and authorizations when Authenticating to Azure

In a hypothetical scenario where I am using Microsoft Identity Platform for authentication, how would I also leverage it to control user permissions. Specifically, user permissions within the custom app. These permissions would not be related to other Azure resources or apps. For example, a web app that allows various different operators of a production plant to enable and disable different systems in the plant such as water coolers, air compressors, and conveyor belts. If I have a web app that allows a user to control these devices on a plant floor, how can I use MSAL to control the permissions to these different areas in the app? I only want user A to control coolers and compressors, and I only want user B to control the belts. I already know how to authenticate the users to the application using MSAL. I would prefer to control the permissions using something similar to AzureAD groups unless there is something better suited to this use case.
Scenario 1:
You have a Web App containing all the business logic. For this scenario you create one app registration for your Web App in Azure AD and define app roles for the various operators. You can name these app roles anything you want, for example: Coolers.Control and Belts.Control.
Example App Registration for Web App with App Roles (Image)
These roles can be assigned to individual users or groups in Azure AD at the Enterprise Application page. If you click on the "How do I assign App roles" on the app roles page, you will find the link that will redirect you to the Enterprise Application page.
If the user navigates to your Web App and signs in using the authorization code flow, the OAuth 2.0 authorization endpoint will return an Identity Token including a roles claim. You can use these roles in your web application to determine what areas the user is allowed to access.
More information: https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-web-app-sign-user-overview?tabs=aspnetcore
Scenario 2:
But there is another option that you might want to consider. You could also create a Web App for UI logic only and place the business logic in a separate Web API. With this architecture you are able to allow multiple (future) client applications to use the functionality of the API, for example: native mobile apps or background apps.
For your scenario you would create two app registrations: one for your Web App and one for your Web API. You define the app roles in the app registration for the Web API and define a scope, for example: access_as_user, to allow delegated access. This scope needs to be assigned to the app registration for your Web App.
Example App Registration for Web API with Scope (Image)
In the Web App you use the access_as_user scope (including app id prefix) in the call to the authorization endpoint. If the user signs in and grants this scope to the Web App so it can call the Web API on behalf of the signed-in user, the authorization endpoint returns an Access Token. If the app roles are defined in the app registration of the Web API and assigned to the user, the Access Token will contain a roles claim. This token is meant for the Web API to authorize the user. When the Web App calls the Web API, it also sends this Access Token in the Authorization Header of the HTTP request. The Web API determines what the user is allowed to do based on the roles in the Access Token.
More information: https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-web-app-call-api-overview
Additional information:
Because I had a similar question, I wrote an article about understanding scopes and app roles in Azure AD. The article explains how to use both scopes and app roles in a delegated access scenario, and how to use app roles in an app-only access scenario. I think this answers your question about how to control the permissions using something similar to Azure AD groups.
URL: https://cloudfirstapproach.com/understanding-oauth-scopes-and-roles-in-azure-ad/

Best way to authorize with AzureAD app registration: roles or group claims when only one AD group is required for access

I have an AzureAD application registration for my front end SPA. I am using Angular with Microsoft’s #azure/msal-angular v2 authentication library. My app registration has all the necessary redirect URIs and configured for proper OAuth2 OpenID Connect using authorization code flow with PKCE. My app is using the Microsoft Graph API with only the User.Read scope. I can authenticate just fine. If my app, however, is only available for one group of people, defined by an AD group and assigned to the Users and Groups section in Azure, what is the best way to validate the logged in user is authorized? I’ve tried enabling optional group claims for the access token, but those don’t come through for some reason. I then tried adding roles-I have an “admin” role, which is the only one I need. This role is assigned to the AD group I mentioned earlier. The roles claim does come back, and I can use that, but this seems silly when I should be able to just validate if the logged in user is in my AD group. The roles approach does have the nice feature of just assigning users different roles to validate authorization for development purposes, but not sure if there’s a better way.
At some point there will be an API I need to plug in. Would it be best to get the claims from that and use that for validation?
Is there a scope or setting I’m missing? Am I achieving this all wrong? Thank you to all who reply.
At this point, you have a SPA that calls a MS 1st party API, which is MS Graph.
Since you are acquiring an accessToken to MS Graph, this accessToken can not be changed - it is meant to be decoded and validated by MS Graph itself, so you will not be able to add any extra claim on that token since you do not control the resource.
Also, your client should treat the accessToken as an opaque string, you should never rely on any claim from the accessToken on the frontend.
You can read more about it here:
https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens
If you want to do some sort of authorization on the frontend, like deciding which routes your user will have access to, you need to rely on the idToken. For the idToken, you can enable the Groups claim and get a list of groups that the user is a member of.
If, as mentioned, later down the line you need to create a custom API and call it from your SPA, then, on that scenario, you can indeed add the Groups claim to the accessToken, because it will be a resource that you control, and then authorize the requests that hit your API based on that claim
MS has a sample that shows exactly how to use security groups for access control, using an Angular frontend with a .NET Core Web API. Give it a check here:
https://github.com/Azure-Samples/ms-identity-javascript-angular-tutorial/blob/main/5-AccessControl/2-call-api-groups/README.md

Want to understand OAuth Code flow where Application passes the Access_Token on user's behalf to the API to get the resources

I like to know my understanding is correct and also like to clarify my doubts further.
1) Confirm my Understanding:
In the below image, I have explained my understanding of protecting the application and api using Azure AD. I have exposed the API with the SCOPE and the Application has consumed the same through the permission module.
Can someone please confirm my understanding is correct?
2) Should we pass Role in ACCESS_TOKEN?
This is where I require someone to help me. This is a code flow where the User login into the Application and while he tries to get the Todo list, an application sends a request to the API.
In this communication, an application gets the ACCESS_TOKEN for the login-in user and passes it to the request going to the API.
At the API side, we have the policy where it checks the Scope coming through IHttpContextAccessor.HttpContext.User.Identity and make sure the Claim has scp/scope and it has the right value.
Now, all are going well. The questions here are:
Should we not have Role (User's role) in the ACCESS_TOKEN? (When I said Role - I mean User's role not Application's role)
following the link at Microsoft documentation I am getting the role in claim when user login to the Application but to call the API I have to use ACCESS_TOKEN which I am getting through TokenAcquisition.GetAccessTokenForUserAsync and it doesn't include Role. It includes SUB, userPreferedName, email and Scope kind of detail (have checked in jwt.io)
If the answer of Question #1 is "NO, we should not" what is the way for API to check the user's role and give the result? Is that something we need to stuff in SCOPE only?
REF: https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-add-app-roles-in-azure-ad-apps
To give better context, I have added my Azure Configuration as well here.
Confirm my Understanding:
Based on your screenshot, your understanding is basically accurate.
Microsoft identity platform issues you an access token after you sign in, and then you use this access token to call your web API. The API will validate the access token and the permissions / roles, which determines whether you can access its data.
This Protocol diagram is clearer for your understanding.
Should we pass Role in ACCESS_TOKEN?
Firstly, the link you shared is related to Application Roles. But you are not talking about that. What you are talking about is the AAD role (eg. Global admin, Group admin). Correct me if there is any understanding.
Honestly, AAD role should not be included in the access token because it's meaningless. To access your web API, you should define your own roles to control the permissions of users. AAD roles only work when you try to perform AAD or Microsoft Graph operations.
If the answer of Question #1 is "NO, we should not" what is the way
for API to check the user's role and give the result?
You have found the correct guide: Add app roles to your application and receive them in the token.
You should use Application Roles. Define the User app role in the Azure AD app which represents your API and assign your users to the role. Then your API can check the user's role by verifying scopes and app roles.
There is another method to control the user's role: using Group Claims which is also mentioned in the link you shared. The detailed steps are listed here.

When to use OBO with Azure

I want to develop a SaaS application on Azure and deploy to the Azure marketplace. This app will be able to obtain information about the user's network. (for instance VNET information). Ideally I would like to have a single-page application that would authenticate with the user who subscribed to the app, and then make calls on a backend API tier, which would make calls to Azure management API endpoints.
The Azure docs layout a number of scenarios of how apps could interface with AD. how-to guides
I believe what im trying to do most closely matches the "Build a web app that calls web APIs" flow, which is an example of OBO. My question is, is that really describing what im doing? Is "calls web APIs" really an example of invoking APIs on the microsoft azure platform?
So my understanding is that I would develop my own API app, that would accept requests from my client browser code, which would contain an oauth token, and then the API layer would derive another token to pass onto the Azure API layer?
Im trying to keep the architecture as simple as possible, but im afraid I may be misinterpreting the Azure docs.
OBO (On-Behalf-Of) allows you to exchange an access token that your API received for an access token to another API.
The important bit is that the access token must have been acquired in the context of the user and must contain user information.
The new access token will then also contain this user's info.
So it allows your back-end API to call Azure Management APIs on behalf of the current user.
This means your API can't do anything the current user can't do.
It is limited to the user's own access rights.
The other option for authentication is to use client credentials authentication,
where your back-end API uses only a client id + certificate/secret to authenticate.
In this case the token will not contain user information.
To enable this approach, the target organization's users would have to assign RBAC access rights to your app's service principal, so it can act by itself.
You could also build a flow in your app where you setup these RBAC accesses on behalf of the current user.
Personally, I would prefer to use delegated access (OBO) whenever possible, as it will block the user from doing things they cannot do.
Though on the other hand, service principal-based access allows the organization to control your app's access better.

Requesting Azure AD permissions on-demand

We have a multi-tenant single page app (and backend) that uses Azure AD for authenticating users. We'd like do queries to customer's Azure AD for retrieving groups but make it an opt-in behavior for customers (tenants). The reasoning behind that is that not all customers necessary need the functionality and would rather not grant us access to their AAD unnecessarily.
Is there some way of implementing this with Azure AD?
I've been trying to test with different OAuth /authorize calls with resource IDs and scopes but mostly I end up with "AADSTS65001: The user or administrator has not consented to use the application with ID ''. Send an interactive authorization request for this user and resource." error. Configuring the web app or backend to require the permission would surely fix the error but that will also make the approval of it mandatory for all users of the app.
Is there a way of using the authorize/consent API to request access to a new application on-demand?
An ugly work-around that should work would be to have 2 client IDs and 2 backend IDs with different permissions but ADAL.js doesn't seem to be designed to work with multiple Client IDs (it's singleton, for starters). Also Application Permissions should of course work but I'm not sure how much of those are required to search for groups.
Is there a way of using the authorize/consent API to request access to
a new application on-demand?
Do take a look at Azure AD v2.0. With their incremental & dynamic consent model, it is possible to do so though I am not sure if this specific functionality (managing groups) is available there.
I had a discussion with Azure AD team member recently about this (as we are also facing the same problem) and he suggested that we take a look at this.
Essentially the way things work in Azure AD v2.0 is that you start with basic set of permissions (like sign in, read profile etc.). Then when some tenant need specific permission, you essentially ask them to grant those permissions to your application at that time only. What this means is that different users in your application have granted different permissions to your application.
If you are using MSAL, and looking for a way to dynamically change your scopes before authenticating, have a look at this: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/v2-docs/configuration.md#msalguard---dynamic-auth-request
More here: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/v2-docs/configuration.md#platformbrowserdynamic

Resources