Azure AD: Grant an appRoleAssignment for a service principal is failing with "code": "Request_ResourceNotFound" - azure-active-directory

I am trying to create a "service principal" for application and to grant admin consent for the permissions using Microsoft graph API.
I followed the following steps:
Created application in a tenant using graph API. My request body is:
{
"displayName": "AppWithPermissions",
"requiredResourceAccess": [
{
"resourceAppId": "00000002-0000-0ff1-ce00-000000000000",
"resourceAccess": [
{
"id": "dc890d15-9560-4a4c-9b7f-a736ec74ec40",
"type": "Role"
}
]
}
]
}
Created a service principal for the above-created application. The creation was successful.
Now, I want to grant admin consent to each assigned permission programmatically using graph API.
To grant application permissions, I created an app role assignment in the appRoleAssignedTo collection of the API's service principal:
The request was as follows:
Post request:
https://graph.microsoft.com/v1.0/servicePrincipals/{id}/appRoleAssignedTo
Request body:
{
"principalId": "principal_id",
"resourceId": "resource_id",
"appRoleId": "approle_id"
}
Here,
"principal_id" is the "id" of service principal created in step 2 above.
"approle_id" is the id of the appRole you want to grant. (taken "id" value from "resourceAccess" array present in "requiredResourceAccess")
"id" in http request url and "resource_id" are the same. (taken "resourceAppId" value from "requiredResourceAccess" which is corresponds to "approle_id" given above)
After running the query, I am getting error 404.
"code": "Request_ResourceNotFound"
for the "resource_id"/"id" field.
Adding screenshots for better understandings:
App Creation:
service principal creation:
Grant an appRoleAssignment for a service principal:
I am confused about which IDs to use where and didn't get a clear idea from the documentations. Can any one please resolve my query? Thanks in advance.

It looks like you're using the appId instead of the id value.
In an app role assignment, resourceId is the id of the servicePrincipal for the resource app (in your case, the API). In an application object's requiredResourceAccess, you use appId, which is a different value.
To find the id of a service principal for which you know the appId:
GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId eq '{app-id}'
The response will contain the id property of the servicePrincipal object, and you can use that when creating the app role assignment.

The document description is not very clear.
In simple terms:
principalId: Usually your service principal id.
resourceId: Usually your service principal id.
appRoleId: For appRoleId you can find it by requesting GET https://graph.microsoft.com/v1.0/servicePrincipals/{id}.
Grant an appRoleAssignment for a service principal:

Related

API Permissions - Microsoft Graph API

I'm using Microsoft Graph API to create an application making an HTTP request using the following documentation:
https://learn.microsoft.com/en-us/graph/api/application-post-applications?view=graph-rest-1.0&tabs=http
Example:
POST https://graph.microsoft.com/v1.0/applications
Content-type: application/json
{
"displayName": "MyAppName",
"signInAudience": "AzureADMultipleOrgs"
}
But I need to add some API permissions (Microsoft Graph Application permissions) when creating the applications so I can do other operations like getting the Azure AD groups, modify them, create users, etc. Is there a way to add and grant the permissions programmatically as well without doing it through the portal?
Thank you.
Microsoft Graph object ID
The first thing you'll need is the object ID of Microsoft Graph service principal in your tenant.
00000003-0000-0000-c000-000000000000 is the globally unique application ID for Microsoft Graph, which we can use to get the object ID by making a request like below.
GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appid eq '00000003-0000-0000-c000-000000000000'&$select=id,appid,appDisplayName
Example response
The object ID we need is the id in the response
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#servicePrincipals(id,appId,appDisplayName)",
"value": [
{
"id": "bd0a624d-11f8-44ab-a015-d8f276d75ad3",
"appId": "00000003-0000-0000-c000-000000000000",
"appDisplayName": "Microsoft Graph"
}
]
}
References
Application IDs for commonly used Microsoft applications
Adding API Permissions
You can add the API permissions, which is separate from granting admin consent.
PATCH https://graph.microsoft.com/v1.0/applications/{application_id}
Headers
Key
Value
Authorization
Bearer {access token}
Content-Type
application/json
Body
Key
Value
resourceAppId
The API resource to add permissions from, in this case 00000003-0000-0000-c000-000000000000 is for Microsoft Graph
resourceAccess
Array of permissions containing the ID and type
id
Use the globally unique ID of the permission want to add, which you can reference from All permissions and IDs
type
For delegated permissions, use Scope. For application permissions, use Role
Example body
The below permissions are for User.Read (delegated), openid (delegated), and Directory.Read.All (application)
{
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
},
{
"id": "37f7f235-527c-4136-accd-4a02d197296e",
"type": "Scope"
},
{
"id": "7ab1d382-f21e-4acd-a863-ba3e13f7da61",
"type": "Role"
}
]
}
]
}
References
Update application API endpoint
requiredResourceAccess resource type
resourceAccess resource type
Granting admin consent
Important to note that you can only grant admin consent with the API for delegated permissions. For application permissions, you'll need to use the Portal and click the button.
POST https://graph.microsoft.com/v1.0/oauth2PermissionGrants
Headers
Key
Value
Authorization
Bearer {access token}
Body
Key
Value
clientId
The Enterprise Application object ID for which you want to grant consent to
consentType
Indicates if authorization is granted for the client application to impersonate all users or only a specific user. AllPrincipals indicates authorization to impersonate all users. Principal indicates authorization to impersonate a specific user. Consent on behalf of all users can be granted by an administrator. Non-admin users may be authorized to consent on behalf of themselves in some cases, for some delegated permissions. Required. Supports $filter (eq only).
resourceId
Use the object ID we obtained earlier for the Microsoft Graph service principal
scope
A space-separated list of the claim values for delegated permissions which you want to grant admin consent to
Example body
{
"clientId": "7f244605-717f-408f-96fb-d369678cea56",
"consentType": "AllPrincipals",
"resourceId": "bd0a624d-11f8-44ab-a015-d8f276d75ad3",
"scope": "openid User.Read"
}
References
Create oAuth2PermissionGrant API endpoint
oAuth2PermissionGrant resource type
Unless you’re creating more then 10 applications, I would just go through the portal.
Creating secrets through the api is not very easy.
The portal has wizards and explanations for most options
Granting permissions and creating applications can be done at the same time, you can also create the application and then have an admin do the admin consent.
Admin consent explained: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#request-the-permissions-from-a-directory-admin

Adding application permission to an client application using MS Graph SDK - Java

I have registered an application with name "API" and for this application I added two App Role in Manifest
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"description": "Demo Role for application.",
"displayName": "Demo Role",
"id": "42ee481e-b4bc-4afa-9499-586bc2a079be",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "demo.role"
},
{
"allowedMemberTypes": [
"Application"
],
"description": "Test Role for application.",
"displayName": "Test Role",
"id": "42ee481e-b4bc-4afa-9499-586bc2a079bd",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "test.role"
}
]
Now I have registered another app called "Client Application" and I want to assign this application above two app roles which I defined in application "API"
From searching the docs I found that we assigning permissions is done to the application service principal, not the Application object.
https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-approleassignedto?view=graph-rest-1.0&tabs=java
Here is the sample code that I found in the documents...
AppRoleAssignment appRoleAssignment = new AppRoleAssignment();
appRoleAssignment.principalId = UUID.fromString("33ad69f9-da99-4bed-acd0-3f24235cb296");
appRoleAssignment.resourceId = UUID.fromString("9028d19c-26a9-4809-8e3f-20ff73e2d75e");
appRoleAssignment.appRoleId = UUID.fromString("ef7437e6-4f94-4a0a-a110-a439eb2aa8f7");
graphClient.servicePrincipals("9028d19c-26a9-4809-8e3f-20ff73e2d75e").appRoleAssignedTo()
.buildRequest()
.post(appRoleAssignment);
principalId: The id of the user, group or client servicePrincipal to which you are assigning the app role. -- Where can I find principalId? Is this the objectId of the "Client Application"?
resourceId: The id of the resource servicePrincipal which has defined the app role. Where can I find resourceId? -- Is this the object ID of "API" Application which has app roles defined?
appRoleId: The id of the appRole (defined on the resource service principal) to assign to a user, group, or service principal. -- I found the app role id - the guid mentioned in app role in manifest of "API" application.
Please assist.
Principal id is the ObjectId but not the actual one which you see in portal but it is the object Id of the service principal and similarly resource Id is objectId of serviceprincipal of resource app.
See the difference from below provided info:
Portal:resourceApp:
App id:51100c0f-xxxx-xxxx-xxxx-xxxxxxxa59,
ObjectId:2275ec6c-xxxx-xxxx-xxxx-xxxxxx2b76e
From powershell commands:
$ResourceId= (Get-AzureAdServicePrincipal -Filter "displayName eq 'testapp'").ObjectId
#output :ResourceId: 36929cef-xxxx-xxxx-xxxx-xxxx989dac7
Portal:client app:
App id:329cd48e-xxxx-xxxx-xxxx-xxxxxxxx2b88,
objectId:9d5e7540-xxxx-xxxx-xxxx-xxxxxxxxx9e1
$principalId=(Get-AzureAdServicePrincipal -Filter "displayName eq 'client app'").ObjectId
#Output : Principal id: 85a53d22-xxxx-xxxx-xxxx-xxxxx300b2
In an app role assignment, resourceId is the id of the servicePrincipal for the resource app ( API app in your case). To find the id of a service principal for which you know the appId through graph api for resource app and client app:see the below request
GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId eq '{app-id}'
(or)
GET https://graph.microsoft.com/v1.0/servicePrincipals/<App id>
Or
GET https://graph.microsoft.com/beta/serviceprincipals?$filter=startswith(displayName, 'Application-Name')
The response will contain the id property of the servicePrincipal object, and you can use that when creating the app role assignment.
Reference:
graph/api/serviceprincipal
When you create/register an application from portal UI, a service principal is created for you automatically however it is not the case when you create application using API calls.
When you register an application using API, you will have to explicitly create service principal for that application...
to create a service principal you need a graph client and object Id of the application you created (please note object Id and app client id is diff) - you can see your object Id from portal UI.
Application application = graphClient.applications(objId)
.buildRequest()
.get();
ServicePrincipal servicePrincipal = new ServicePrincipal();
servicePrincipal.appId = application.appId;
graphClient.servicePrincipals()
.buildRequest()
.post(servicePrincipal);
Now you have created a service principal for you application...next up is finding the ID which you can do like this...
ServicePrincipalCollectionPage servicePrincipals = graphClient.servicePrincipals()
.buildRequest()
.get();
List<ServicePrincipal> list = servicePrincipals.getCurrentPage();
Go through the list and choose your application based on display name, and you can find ID too.
ServicePrincipal.Id --> This is what you need...
and based on your need...
The principalId is the client app which you created - so you need servicePrincipal.Id of that application.
The resourceId is the app where you defined your approles - so you need servicePrincipal.Id of that application.

Tenant 'xxx' not found while calling MS Graph API on behalf of a user

I'm trying to implement the on behalf flow with Azure AD following this Microsoft sample documentation, all is good on the client-side but in the
the service app side (the azure function that obtains another Access Token using the on user's behalf and calls the MS Graph API on user's behalf again), it fails to obtain the access a new access token (getNewAccessToken) and shows:
{
"error": "invalid_request",
"error_description": "AADSTS90002: Tenant 'xyz' not found. This may happen if there are no active subscriptions for the tenant. Check to make sure you have the correct tenant ID. Check with your subscription administrator.\r\nTrace ID: xxx \r\nCorrelation ID: yyy \r\nTimestamp: 2021-01-04 07:17:15Z",
"error_codes": [
90002
],
"timestamp": "2021-01-04 07:17:15Z",
"trace_id": "xxx",
"correlation_id": "yyy",
"error_uri": "https://login.microsoftonline.com/error?code=90002"
}
any clue how to solve this issue?
Based off your error message, you can navigate to your Azure Active Directory and make sure your TenantID matches what's in your application.
Error Message:
AADSTS90002: Tenant 'xyz' not found. This may happen if there are no active subscriptions for the tenant. Check to make sure you have the correct tenant ID.
TenantID

Write requests are only supported on contained entities, Microsoft Graph API when trying to PATCH/POST to assign AD App role to user

I'm trying to assign app-specific roles to a user in our AD group using Microsoft Graph.
The link I'm sending the request to:
https://graph.microsoft.com/beta/users/{oID of the user I want to assign the role to}/appRoleAssignments/{Object ID of the AD enterprise app}
Inside the request:
{"id": "ID of the role I'm trying to assign to the user"}
The error:
"code": "BadRequest",
"message": "Write requests are only supported on contained entities",
The documentation doesn't define parameters in the example well and I've tried various possibilities but this is the only meaningful result I've gotten.
This isn't current supported by Microsoft Graph. To create app role assignments, you'll need to use Azure AD Graph:
POST https://graph.windows.net/myorganization/users/{user-object-id}/appRoleAssignments
{
"principalId": "{user-object-id}",
"resourceId": "{service-principal-object-id}",
"id": "{app-role-id}"
}

Adding users with roles into app registration

I can see you can create app registrations with graph API but is it possible to add users and roles to an app registration?
If you want to assign a user to that application, in one of the specified app roles, you'll need to set the appRoleAssignment on the user . If using Azure AD Graph api , you could use below rest api :
https://graph.windows.net/{tenant-id}/users/{username}/appRoleAssignments?api-version={api-version}
Content-Type:application/json
Authorization: Bearer {token}
{
"id": "RoleID",
"principalId": "UserObjectID",
"principalType": "User",
"resourceId": "servicePrincipalID"
}
id: This is the Id for the Role you are assigning. These Ids can be found in the Application's Manifest. Or you could use below api to get the specific role defined for your application(appRoles claim):
https://graph.windows.net/{tenant}/applications/{ObjectIDOfApplication}?api-version=1.6
principalId :This is the Obeject Id of the User you are assigning the role to.
principalType :If you are assigning this role to a User then this is set to the string User .
resourceId : Service Principal ID of the application . To get service principal id , you could use below api (objectId claim) :
https://graph.windows.net/{tenant}/servicePrincipals?api-version=1.6&$filter=appId eq 'appid'
Application role assignments are available in the Microsoft Graph Beta endpoint: see Update approleassignment
To give you an idea of what could do to add app role assignments to a user, I suggest you look at the Configure.ps1 PowerShell script of the active-directory-dotnet-webapp-roleclaims sample on GitHub, which creates test users of a given role and updates the application registration. This is in PowerShell, but you should be able to adapt it to using MSGraph

Resources