In my early post, I have explained about administrator consent (admin consent) in Microsoft Entra ID (Azure AD). The admin consent is very useful and needed for the various scenarios, such as app permissions (application-level privilege without interactive sign-in UI), granting entire employees without individual user consents, or on-behalf-of flow in your web api.
For the use of admin consent, you must pre-define the permissions in Azure Portal. But, in the UI, you can set the scopes only for well-known API, such as Microsoft Graph, Power BI, and so on (see the following screenshot), and some ISV folks ask me how to use admin consent for 3rd party apps or legacy APIs (Outlook Rest API, etc) ?.
The answer is “edit manifest by your own !”
In this post I show you how to configure this custom settings in Entra ID with application manifest step-by-step.
Permissions in Entra ID (Azure AD v2 endpoint) – Under the hood
Now let’s take a look at predefined scopes in Entra ID.
For realizing scenarios such as application permissions (application-level privilege without interactive sign-in UI), granting entire employees without individual user consents (delegated permissions) and so on, you can pre-define the needed scopes to the application within Azure Portal (Azure AD management).
Note : For the usual user consent, you don’t need to pre-define scopes in Entra ID and you can set scopes dynamically (on the fly) when you authenticate.
This pre-defined permission is needed for admin consent.
These settings are all written in the application manifest at the bottom, and you can edit the manifest directly with “Manifest” command (see below) in the navigation on Entra ID management.
For example, when you set “offline_access” scope and “openid” scope in your app, these are written in the manifest as follows.
{ "id": "678806b7-adee-4f4e-b548-947e10512e00", "appId": "c471620b-73a3-4a88-a926-eda184e6fde9", "name": "testapp01", "oauth2AllowImplicitFlow": false, "requiredResourceAccess": [{ "resourceAppId": "00000003-0000-0000-c000-000000000000", "resourceAccess": [{ "id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182", "type": "Scope"},{ "id": "37f7f235-527c-4136-accd-4a02d197296e", "type": "Scope"} ]} ], ... }
As you can see, both app ID and scope ID are used for settings. For example, 00000003-0000-0000-c000-000000000000
means “Microsoft Graph” application and 7427e0e9-2fba-42fe-b0c0-848c9e6a8182
means “offline_access” scope.
The following is the list of IDs for the familiar scopes. (All scopes are in “Microsoft Graph” application.)
openid | 37f7f235-527c-4136-accd-4a02d197296e |
64a6cdd6-aab1-4aaf-94b8-3cc8405e90d0 | |
profile | 14dad69e-099b-42c9-810b-d002981feec1 |
offline_access | 7427e0e9-2fba-42fe-b0c0-848c9e6a8182 |
In conclusion, you just edit the manifest by your own, when you need to add custom scopes except for well-known Microsoft application.
The next concern is : How to get (look for) the app id and scope id ?
Use permissions for other APIs
Note : Here I use Outlook REST API (not Microsoft Graph) as legacy API in our example. However, Outlook REST API will retire on 11/30/2022. (See here.)
When you want to use Outlook REST API, OneDrive API, Power BI REST API, so on and so forth …, you should go to Entra ID (Azure AD) settings in Azure Portal at first.
In this settings, you can set these APIs for required permissions and you can see the app id and scope id in the manifest text as follows. (The following is the sample for https://outlook.office.com/mail.read scope.)
You can use same ID in v2 endpoint and can set these scopes using the manifest editor in Azure Portal (Entra ID management) as follows.
{ "id": "678806b7-adee-4f4e-b548-947e10512e00", "appId": "c471620b-73a3-4a88-a926-eda184e6fde9", "name": "testapp01", "oauth2AllowImplicitFlow": false, "requiredResourceAccess": [{ "resourceAppId": "00000003-0000-0000-c000-000000000000", "resourceAccess": [{ "id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182", "type": "Scope"},{ "id": "37f7f235-527c-4136-accd-4a02d197296e", "type": "Scope"} ]},{ "resourceAppId": "00000002-0000-0ff1-ce00-000000000000", "resourceAccess": [{ "id": "185758ba-798d-4b72-9e54-429a413a2510", "type": "Scope"} ]} ], ... }
Now let’s access the following admin consent url in v2 endpoint with your browser. (Change testdirectory.onmicrosoft.com
, c471620b-73a3-4a88-a926-eda184e6fde9
, and https://localhost/testapp01
for your appropriate values.)
https://login.microsoftonline.com/testdirectory.onmicrosoft.com/adminconsent?client_id=c471620b-73a3-4a88-a926-eda184e6fde9&state=12345&redirect_uri=https%3a%2f%2flocalhost%2ftestapp01
After you logged-in by the administrator account, the following consent screen is displayed. Note that this Mail.Read scope is not in Microsoft Graph, but in Outlook REST API. Therefore when you get your own e-mails in your inbox, you must access https://outlook.office365.com/api/{version}/me/messages instead of using https://graph.microsoft.com/{version}/me/messages. (You cannot use https://graph.microsoft.com/{version}/me/messages with this consent.)
Use permissions for unknown ISV applications
As I mentioned in my early post “Build your own Web API protected by Entra ID with custom scopes“, you can define your own custom scopes for your API applications.
For example, we assume that 2 scopes in our api application are defined as the following screenshot in Entra ID (Azure Portal).
These scopes will be written in the manifest as follows.
In this case, the app ID is 7c830491-d224-4cc2-8821-71c1e9ec58ac
, and the scope IDs are 223e6396-1b01-4a16-bb2f-03eaed9f31a8
and 658e7fa5-bb32-4ed1-93eb-b040ebc6bfec
.
{ "id": "2cd5c8e0-6a6c-4e8d-870c-46c08f3be3d9", "appId": "7c830491-d224-4cc2-8821-71c1e9ec58ac", "identifierUris": ["api://7c830491-d224-4cc2-8821-71c1e9ec58ac" ], "oauth2Permissions": [{ "adminConsentDescription": "Allow the client to write your data with myapi01 on behalf of the signed-in user.", "adminConsentDisplayName": "Write data with myapi", "id": "223e6396-1b01-4a16-bb2f-03eaed9f31a8", "isEnabled": true, "lang": null, "origin": "Application", "type": "User", "userConsentDescription": "Allow the client to write your data with myapi01 on your behalf.", "userConsentDisplayName": "Write data with myapi", "value": "write_as_user"},{ "adminConsentDescription": "Allow the client to read your data with myapi01 on behalf of the signed-in user.", "adminConsentDisplayName": "Read data with myapi", "id": "658e7fa5-bb32-4ed1-93eb-b040ebc6bfec", "isEnabled": true, "lang": null, "origin": "Application", "type": "User", "userConsentDescription": "Allow the client to read your data with myapi01 on your behalf.", "userConsentDisplayName": "Read data with myapi", "value": "read_as_user"} ], ... }
Therefore, on the client side (which uses above API scopes), you can set these scopes of the application using the manifest editor as follows.
{ "id": "678806b7-adee-4f4e-b548-947e10512e00", "appId": "c471620b-73a3-4a88-a926-eda184e6fde9", "name": "testapp01", "oauth2AllowImplicitFlow": false, "requiredResourceAccess": [{ "resourceAppId": "00000003-0000-0000-c000-000000000000", "resourceAccess": [{ "id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182", "type": "Scope"},{ "id": "37f7f235-527c-4136-accd-4a02d197296e", "type": "Scope"} ]},{ "resourceAppId": "7c830491-d224-4cc2-8821-71c1e9ec58ac", "resourceAccess": [{ "id": "658e7fa5-bb32-4ed1-93eb-b040ebc6bfec", "type": "Scope"} ]} ], ... }
Otherwise, if you have already consented API application in your tenant, you don’t need to use manifest editor and you can set this API scope (permission) by clicking “APIs my organization uses” tab on app permission selection. (See below.)
If you try to set your own custom API scope (permission), just click “My APIs” tab.
In order to use this permission in client application, first the user (administrator) must subscribe the API application.
Let’s access the following URL, in which 7c830491-d224-4cc2-8821-71c1e9ec58ac
is the app ID of the API application. (See my early post “Build your own Web API protected by Entra ID with custom scopes” for details.)
https://login.microsoftonline.com/testdirectory.onmicrosoft.com/adminconsent?client_id=7c830491-d224-4cc2-8821-71c1e9ec58ac&state=12345&redirect_uri=https%3a%2f%2flocalhost%2fmyapi01
After you’ve subscribed the api application, now let’s access the following admin consent url for the client application, in which c471620b-73a3-4a88-a926-eda184e6fde9
is the app ID of the client side.
https://login.microsoftonline.com/testdirectory.onmicrosoft.com/adminconsent?client_id=c471620b-73a3-4a88-a926-eda184e6fde9&state=12345&redirect_uri=https%3a%2f%2flocalhost%2ftestapp01
After you logged-in with the administrator account, you can find that the following consent screen is displayed.
Update History :
Dec 04, 2019 Update App Registration Portal (https://apps.dev.microsoft.com) to Azure Portal, because of App Registration Portal deprecation
Categories: Uncategorized
The list of GUIDs is incorrect, e.g. one GUID is repeated twice, I guess a copy/paste error. The GUID for profile is 14dad69e-099b-42c9-810b-d002981feec1, not 37f7f235-527c-4136-accd-4a02d197296e.
LikeLiked by 1 person
Thank you, Random visitor-san. You’re right and now I fixed my post.
(Thanks again for your feedback !)
LikeLike
I feel that is among the such a lot significant info for me.
And i am satisfied reading your article. But should observation on some common things,
The web site style is great, the articles is really great : D.
Just right task, cheers
LikeLike
Ok. Good article. Thanks a lot. But what about custom permissions defined outside of Azure.
Let’s say my app is a SaaS from a third party provider. And I would like to use AAD to manage authN & authZ to emit JWT token that contains permissions (claim “scopes”) associated to app roles or permissions allowed (consent) by admin at the time of registration of the app. Is it possible ?
LikeLike
You can define your own scope and generate a token with that custom token. But this token should be validated with certificate in Azure AD, and “SaaS app outside of Azure” must then be federated with Azure AD in SaaS platform’s identity mechanism. (Then this validation will be submitted in SaaS application.) As you know, a variety of SaaS (Google, Saleforce, etc) has these federation mechanism along with open standards.
For details about token validation, see below.
Does that (my answer) make sense?
LikeLike