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

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}"
}

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

AD provisioning says that "A required attribute is missing from a response", but it does exist in the response

I'm working on implementing SCIM 2.0, as I need to use to to provision users in my system that are stored in Azure AD. I have set it up and when I try to manually provision a user, I get this error:
The user is successfully provisioned on the client side, as you might guess from the error message - it's not an issue with the request.
I am guessing that the issue is with where the identifier is located, since the Identifier attribute is included in the response that is in the error message.
I've googled this error and I can find general tutorials for AD SCIM implementations, but I haven't been able to find anything about this specific error.
Here's a pretty-printed version of the response:
{
"totalResults": 1,
"startIndex": 0,
"itemsPerPage": 1,
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
],
"Resources": [
{
"emails": [
{
"type": "work",
"value": "perrin#***.com",
"primary": true
}
],
"Identifier": "1072",
"meta": {
"meta": "/scim/v2/Users/1072",
"resourceType": "User"
},
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User"
],
"name": {
"familyName": "Aybara",
"givenName": "Perrin"
},
"active": true,
"id": "1072",
"userName": "perrin#***.com"
}
]
}
• As you are provisioning a user manually through SCIM functionality of Azure AD, the issuer identity, i.e., Azure AD is identified by an iss claim in the token received after successfully provisioning the user from Azure AD. Example of it is as below: -
"iss":https://sts.windows.net/cbb1a5ac-f33b-45fa-9bf5-f37db0fed422/
where ‘https://sts.windows.net’ is the URL of the issuer, i.e., Azure AD and the ‘cbb1a5ac-f33b-45fa-9bf5-f37db0fed422’ is the unique identifier of the Azure AD tenant for which it was issued. This token was issued for the application template ID of the app configured for provisioning in enterprise applications.
• Also, please note that the query to provision an Azure AD user with the ‘create’ action in the client app web service with an ‘externalId’ attribute value that matches the ‘mailNickname’ attribute value of a user doesn't return any users in your case as shown in the image, then AAD requests that the web service provision a user corresponding to the one in AAD. The user provisioned from Azure AD is assigned an identifier value when the provisioning succeeds and returns an instance of the Microsoft.SCIM.Core2EnterpriseUser class with identifier attribute indicating the user provisioned. Thus, since the user identifier value is missing as shown in the image, please run the below command to query whether the user is created successfully or not.
‘ GET ~/scim/Users/54D382A4-2050-4C03-94D1-E769F1D15682 HTTP/1.1
Authorization: Bearer ... ’
In a request to retrieve the current state of the user provisioned, the values of the properties of the object provided as the value of the parameters argument are as follows:
Identifier: "54D382A4-2050-4C03-94D1-E769F1D15682"
SchemaIdentifier: "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
• Request you to try again to provision the user and query to request the current state of the user regarding its reference attribute. Also, send a request from Azure AD to the SCIM service to update the user in its datastore. Here is an example of the request sent from Azure AD to the SCIM service: -
‘ PATCH ~/scim/Users/54D382A4-2050-4C03-94D1-E769F1D15682 HTTP/1.1
Authorization: Bearer ...
Content-type: application/scim+json
{
"schemas":
[
"urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations":
[
{
"op":"Add",
"path":"manager",
"value":
[
{
"$ref":"http://.../scim/Users/2819c223-7f76-453a-919d-413861904646",
"value":"2819c223-7f76-453a-919d-413861904646"}]}]} ‘
Please find the detailed steps in the link as below: -
https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups#handling-provisioning-and-deprovisioning-of-users
This error generally shows up when there is something invalid with the format of the JSON payload. From looking at this one, I suspect it's your inclusion of "Identifier" as this is not defined in the core SCIM schema docs, and specifically may be causing issues if it overlaps with something else in the provisioning service. "id" is the correct attribute to use.
After playing around with it the issue was not that the resources were missing anything - it was the ListResponse itself that needed an ID. If I include
"id": "urn:ietf:params:scim:api:messages:2.0:ListResponse"
to the top-level object (along with totalResults, etc.) it is processed as expected.

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

Unable to delete user from Azure AD B2C

According to this article it should be possible to delete a user from Azure AD B2C using the Microsoft Graph API: https://learn.microsoft.com/en-us/azure/active-directory-b2c/microsoft-graph-operations (more specifically: https://learn.microsoft.com/en-us/graph/api/user-delete)
I have set the User.ReadWrite.All permission (for permission type Application) and granted admin consent.
However, when calling the corresponding endpoint with a http DELETE request, it fails with the following response:
{
"odata.error": {
"code": "Authorization_RequestDenied",
"message": {
"lang": "en",
"value": "Insufficient privileges to complete the operation."
},
"requestId": "b129b3a7-a0e9-42db-aa7a-97da31590095",
"date": "2020-11-04T12:53:32"
}
}
Other operations (such as listing and updating users) work perfectly fine. Does anyone know what causes this behavior? Any help is highly appreciated.
Update:
This is a sample of a request which I try to send to the Graph API:
Postman Curl request
Make sure you are calling Microsoft Graph and the configured permissions are under Microsoft Graph.
Based on your Curl request, you are calling Azure AD Graph (endpoint https://graph.windows.net).
The Microsoft Graph endpoint is https://graph.microsoft.com.
If your permissions are set correctly under Microsoft Graph, try to use DELETE https://graph.microsoft.com/v1.0/users/{user-id} to delete the user.

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

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:

Resources