We created a sharepoint add-in with the follow permissions:
<AppPermissionRequests AllowAppOnlyPolicy="true"><AppPermissionRequest Scope="http://sharepoint/content/tenant" Right="Read"/></AppPermissionRequests>
My understanding is that an app with tenant scope permissions should be able to read all the site contents. In this case the call to
/_api/web/lists('<id>')/items(<id>)/roleassignments
fails with the following error:
Client error 403
{
"odata.error":
{
"code":"-2147024891, System.UnauthorizedAccessException",
"message":
{
"lang":"en-US",
"value":"Access denied. You do not have permission to perform this action or access this resource."
}
}
}
Note that a call to /_api/web/lists('<id>')/items(<id>) for the same item works fine. The roleassignments call with tenant permissions is also working for one of the SPO instances but not for a different one.
We've struggled with this issue on and off, because the solution is not obvious, nor even sensible from a least-privilege perspective. In short:
Your application requires FullControl rights in order to access RoleAssignments.
More details
If using an application created by Azure AD, you can demonstrate this by granting and consenting to SharePoint permissions such as:
AllSites.Read (delegated)
MyFiles.Read (delegated)
Sites.Selected (application)
User.Read.All (delegated)
User.Read.All (application)
If using SharePoint-created application, use appregnew.aspx and appinv.aspx to create the app and grant it Read rights at some reasonable scope; try http://sharepoint/content/tenant.
Then get a bearer token using a client_credentials workflow (use Postman, for example).
Try a query like:
https://your-tenant.sharepoint.com/_api/web/GetFolderByServerRelativeUrl('/Shared Documents')/Files?$select=Length,TimeLastModified,ListItemAllFields,ServerRelativeUrl
Make sure the Authorization header value is Bearer your-access-token
It will work.
Now try the same query, but with getting role assignments:
https://your-tenant.sharepoint.com/_api/web/GetFolderByServerRelativeUrl('/Shared Documents')/Files?$select=Length,TimeLastModified,ListItemAllFields,ServerRelativeUrl&$expand=ListItemAllFields/RoleAssignments/RoleDefinitionBindings/Name
It will fail as you described, with status 403 and System.UnauthorizedAccessException.
Now grant and consent to the SharePoint application permission Sites.FullControl.All, or use appinv.aspx to add FullControl rights. Get a new bearer token. (The old one encodes the old rights granted to the app in the role field of the payload.). You'll need to wait a few minutes until the permissions apparently propagate from AD to SharePoint, if you're using an Azure AD application.
Try the last query again, and it will work.
IMHO, requiring FullControl in order to resolve something like a role assignment, which is needed to capture the permissions required to access content in a SharePoint library, is unjustified. I could understand, sort of, if tenant-scope Read permission were required. However, granting AllSites.Read or tenant-scope (http://sharepoint/content/tenant in appinv.aspx XML permissions) doesn't seem to enable roleassignment lookup.
Related
I understand the process of assigning Microsoft Graph permissions to a service principal. I can take the object id of the Microsoft Graph app, then use the https://graph.microsoft.com/v1.0/servicePrincipals/<id>/appRoleAssignedTo MSGraph endpoint, like described here.
My question is: can I do the same with a regular user? That is, when calling appRoleAssignedTo, specify the object id of a user in the principalId field. Can a regular user have application permissions (like MSGraph permissions), and how do I use them afterwards?
I tried to do the above and assign the RoleManagement.ReadWrite.Directory to a user. Then I logged in with az login and ran az account get-access-token --resource-type ms-graph.
With this token I tried to do an operation that requires the RoleManagement.ReadWrite.Directory permission, like assigning a role to another user, but it fails with Insufficient privileges to complete the operation..
Users can request the scope they need when using Connect-MgGraph, for example:
Connect-MgGraph -Scopes "RoleManagement.ReadWrite.Directory"
Which is the recommended approach, as it means that for that session they will only have access to the scopes that are necessary rather than any they've previously requested
I tried to reproduce the same in my environment and got the same error as below:
Note that: Microsoft Graph API permissions can be assigned only to Service principals not users directly.
When I tried to Connect-MgGraph as a normal user, I got the error like below:
Connect-MgGraph -Scopes "RoleManagement.ReadWrite.Directory"
I created an Azure AD Application and granted API permission as below:
I generated access token by using below parameters:
GET https://login.microsoftonline.com/1810a95e-99f3-46e0-84e8-8a2aee05d830/oauth2/v2.0/token
client_id:ClientID
client_secret:*****
scope:RoleManagement.ReadWrite.Directory
grant_type:authorization_code
redirect_uri:RedirectUri
code:code
By using the above access token, I am able to assign directory role to the user successfully as below:
POST https://graph.microsoft.com/v1.0/directoryRoles/roleTemplateId=88d8e3e3-8f55-4a1e-953a-9b9898b8876b/members/$ref
Content-type: application/json
{
"#odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/UserID"
}
Reference:
Add graph api permission to user account by Harpreet Singh Matharoo
I am trying to add a user role to a subscription in Azure using REST API following this documentation.
I got a bearer token with my login and passed it as a header Authorization parameter.
Gave all the values as described in the doc
PFA REST API call I performed.
API response says below;
{
"error": {
"code": "AuthenticationFailed",
"message": "Authentication failed."
}
}
Please let me know if any one successfully used this API and performed operations. Also is there any Azure .NET API to this operation?
REST API Postman request
The error means your user account does not have the permission to create the role assignment, specifically Microsoft.Authorization/roleAssignments/write.
To solve the issue, you need to ask the admin who is the Owner or User Access Administrator(or custom RBAC role with Microsoft.Authorization/roleAssignments/write permission) of your subscription to assign the Owner or User Access Administrator or custom role with the permission above for you at the subscription scope first, follow this link, then get a new token, you will be able to assign the role to others like the admin assign the role to you i.e. create role assignment.
Update:
If you want to get the access token via your user credential, you could use the auth code flow, please follow the steps below.
1.In your App registration, add the user_impersonation Delegated permission of Azure Service Management API.
2.Hit the URL below in the browser, change the tenant-id, client-id, redirect_uri to yours, login your user account.
https://login.microsoftonline.com/tenant-id/oauth2/v2.0/authorize?
client_id=xxxxxxxx
&response_type=code
&redirect_uri=http://localhost
&response_mode=query
&scope=https://management.azure.com/.default
&state=12345
Then you will get a code like below, copy it.
Don't forget to remove the state and session_state.
3.In the postman, use the query below, then you can get the token.
I'm trying to get a subscription created with the callRecord resource (https://learn.microsoft.com/en-us/graph/api/subscription-post-subscriptions?view=graph-rest-beta&tabs=http)
In the app registration section of the Azure portal, I've created a multi-tenant app with a client secret. That app has permissions for application-level "CallRecords.Read.All" as well as the default delegated "User.Read". The statuses also have a green checkbox for being granted against my organization by an admin.
I am able to get an access token with the following HTTP POST request to https://login.microsoftonline.com/common/oauth2/v2.0/token:
grant_type:authorization_code
scope:https://graph.microsoft.com/.default
client_secret:<client_secret>
client_id:<client_id>
code:<code>
redirect_uri:http://localhost:3000
However, that token is not able to generate a subscription to my callRecord resource. I get a response with this message: "Operation: Create; Exception: [Status Code: Forbidden; Reason: The request is not authorized for this user or application.]"
The message suggests that the app has not been granted admin-level authorization, but in fact it has. This used to work for me. I'm wondering if there has been a regression on the MS Graph side.
Further, when I examine the JWT, I see that the scope is "User.Read profile openid email". There is no mention of the application-level permission (specifically, CallRecords.Read.All)
Thanks.
Because when you use the auth code flow, just the Delegated permission will take effect. So even if you grant the Application permission, the token you got will not include the permission.
From the doc, to call this API Get callRecord, just the Application permission is supported.
To get the token which include the permission, your option is to use the client credential flow.
Note: You need to use <tenant-id> instead of common in this flow.
POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
client_id=xxxxxxx
&scope=https://graph.microsoft.com/.default
&client_secret=xxxxxxx
&grant_type=client_credentials
Decode the token in https://jwt.io, the roles includes the CallRecords.Read.All permission:
I get an "Unauthorized" status code (401) when I call MS Graph from my Logic App.
The MS Gaph URI I'm calling has been tested separately using Graph Explorer to insure that it was a properly formed request.
I'm guessing that the issue has to do with Application Permissions needing to be granted to the AD App registration.
The Logic App is not prompting the user to grant the "Delegated" permissions I added to the App Registration. This is why I'm guessing, I need to use Application permissions instead of Delegated permissions.
Here is the error being returned
{
"error": {
"code": "NoPermissionsInAccessToken",
"message": "The token contains no permissions, or permissions can not be
understood.",
"innerError": {
"request-id": "8addc6d3-fbf1-4a61-8ed2-b4593a10dd8c",
"date": "2019-07-16T12:29:27"
}
}
}
I would of course Grant the Application permissions myself in order to test this, but I don't have rights, and I need to research this a bit before I approach our admins.
You are right. You need grant the application permissions to your app. The Active Directory OAuth in logic app uses client credentials flow which doesn't need user interaction.
Here is the difference between application permission and delegated permission.
I've seen posts like this one where there is confusion on exactly what permission is required to allow a ServicePrincipal to call Get-AzureRmRoleAssignment when logging in using Login-AzureRmAccount.
In my case if I call Get-AzureRmRoleAssignment with the -debug flag I can capture the following error in the body of the HTTP response:
Body:
{
"odata.error": {
"code": "Authorization_RequestDenied",
"message": {
"lang": "en",
"value": "Insufficient privileges to complete the operation."
}
}
}
I have set perms for the application as follows... first the Azure AD access:
And then the Microsoft Graph access:
This still gives the authZ failure error. I have even tried an experiment where I gave the app ALL perms for each API, and that still did not work.
What's missing? What perms EXACTLY are needed to allow read only programmatic access to list the role assignments with this call?
First, as I answered in that case, Get-AzureRmRoleAssignmentdoesn't only needs read access for role assignment with Azure REST API permission but also needs Read directory data permission with Azure AD Graph API. After adding permissions,
Add AAD Graph API Permission:
You also need to click Grant permissions button to do admin consent.
Add Azure REST API Persmssions:
Also, before adding AAD graph API permissions for your sp, ensure your sp has permissions with Azure REST API by assigning a role (E.g. A Contributor Role) to it from Subscriptions RBAC(IAM).
I test this and succeeded.