Microsoft Azure - Assigning Microsoft Graph permissions to a regular user doesn't work - azure

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

Related

How can I grant consent to my own app in azure, in case I am not global admin in tenant?

Given I have created an app using this repository in Azure.
And this app is deployed using a Service Principal which was created by below command:
az ad sp create-for-rbac --name "fxpricepredictor" --role contributor --scopes "/subscriptions/YOUR-SUBSCRIPTION-ID/resourceGroups/YOUR-RESOURCE-GROUP-NAME" --sdk-auth
Now, I need to get the API token to manage my created resources using REST APIs.
Based on documentation, I should be able use my tenantId, clientId and client_secret to get the token by calling the bellow endpoint:
curl: POST
https://login.microsoftonline.com/{{tenantId}}/oauth2/token
Please notice that, I am not the global admin in the tenant.
The official sample postman collection is here and here is how my request looks like in postman:
Sadly the endpoint does not provide me the token and instead it returns such error:
{
"error": "unauthorized_client",
"error_description": "AADSTS700016: Application with identifier 'MY_CLIENTID' was not found in the directory 'MY COMPANY'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant.\r\nTrace ID: 5a9a2c53-c3c8-46da-a1a6-551b42082400\r\nCorrelation ID: bf7c5966-ffa4-4312-8a77-434c2560d65a\r\nTimestamp: 2022-10-05 14:54:23Z",
"error_codes": [
700016
],
"timestamp": "2022-10-05 14:54:23Z",
"trace_id": "5a9a2c53-c3c8-46da-a1a6-551b42082400",
"correlation_id": "bf7c5966-ffa4-4312-8a77-434c2560d65a",
"error_uri": "https://login.microsoftonline.com/error?code=700016"
}
please notice, I hided some sensitive values in error response by MY_CLIENTID and MY COMPANY
So, i guess, the main reason that i am facing this issue is that:
This can happen if the application has not been consented to by any user in the tenant.
Meaning that, i should consent my own app. Am I right ?
So, my question is:
How can i get the token to work with REST APIs to manage my resources ?
How can I grant consent to my own app, given that I am not a global Admin ?
Update:
As I figured out, I should be able to Grant Consent to my app using "Microsoft Graph permissions reference". And here is what i have done:
Login to Azure portal
Navigate to "Azure Active Directory"
Navigate to "App registrations"
Click on the created APP ("fxpricepredictor")
Navigate to "API permissions"
Click "Add a permission"
Click on "Microsoft Graph"
Choose "Delegated Permissions"
Search for "authentication" ---> (Sadly this option also requiereds Admin Consent)
I tried to reproduce the same in my environment and got the below results:
When I ran the same command as you, one Azure AD application named fxpricepredictor is automatically created with details like below:
az ad sp create-for-rbac --name "fxpricepredictor" --role contributor --scopes "/subscriptions/<subscriptionID>/resourceGroups/<resourcegroupName>" --sdk-auth
By including above details as parameters, I am able to generate access token successfully via Postman like below:
Please note that, I don't have global administrator role and granting admin_consent is not really required.
With the above access token, I am able to fetch and manage the Azure resources in that resource group like below:
GET https://management.azure.com/subscriptions/<subscriptionID>/resourceGroups/SriTest/resources?api-version=2021-04-01
Response:
The error AADSTS700016 may also occur if there is no application in your tenant with provided ClientID.
I tried including random ClientID which does not exist in Azure AD tenant and got same error as below:
So, make sure to check whether the application is existing or not with the given ClientID in Azure AD tenant.

Microsoft Azure OAuth Client Credentials Token gets "AuthorizationFailed" response

I want create APIM subscriptions through rest api, And was able to do it successfully by following this Microsoft doc, https://learn.microsoft.com/en-us/rest/api/apimanagement/current-ga/subscription.
And for Authentication I am generating a bearer token using ROPC grant type(My UserName & Password). Everything works fine with this flow.
But i dont want to configure my username & password in a application to get a bearer token, instead i followed Client-Credentials grant type(get token by client id & secret), i am able to generate token, but when i use that token to create subscription in APIM, i am getting a exception
The client '0--e' with object id '0--e' does not have authorization to perform action 'Microsoft.ApiManagement/service/subscriptions/write'
Is it possible to add a AAD application inside APIM AccessControl(IAM) to grant permission.
Or is this any other way to do this? or ROPC is the only way?
Can someone please help.
Yes, you can grant permission to AAD application (service principal) in APIM Access Control (IAM) by assigning it API Management Service Contributor role.
I tried to reproduce the same in my environment and got the below results:
I have generated one access token using Client-Credentials grant type like below:
When I used the above token to create APIM subscription with below query, I got the same error:
PUT https://management.azure.com/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.ApiManagement/service/apimService1/subscriptions/testsub?api-version=2021-12-01
{
"properties": {
"ownerId": "/subscriptions/subid/resourceGroups/rgname/providers/Microsoft.ApiManagement/service/servicename/users/xxxxxxxxxxx",
"scope": "/subscriptions/subid/resourceGroups/rgname/providers/Microsoft.ApiManagement/service/servicename/products/xxxxxxxxxxx",
"displayName": "testsub"
}
}
Response:
To resolve the error, you need to grant API Management Service Contributor role for that application like below:
Go to Azure Portal -> APIM Services -> Your APIM -> Access control (IAM) -> Add role assignment
After granting the above role, I generated the access token again and ran the same query as below:
PUT https://management.azure.com/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.ApiManagement/service/apimService1/subscriptions/testsub?api-version=2021-12-01
Response:
When I checked the Portal, APIM subscription got created successfully like below:
Reference:
How to use Role-Based Access Control in Azure API Management | Microsoft Docs

Why doesn't Azure REST API to assign user role to a subscription work?

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.

How do I specify Permissions in a custom app consent policy?

I have successfully made a Custom App Consent Policy using New-AzureADMSPermissionGrantConditionSet and following the MS docs. I specified ClientApplicationIds and it works great.
Now I also want to specify the permissions that must match. On Permissions, the docs say:
I need help understanding (and accessing) the permission IDs in the "OAuth2Permissions property of the API's ServicePrincipal object".
What ServicePrincipal is the doc referring to? The one in the application’s Home Tenant, or one in the Tenant that is using the application? If the app has not been consented to yet, then there is no ServicePrinciple in the Tenant using the app so I have a chicken-and-egg problem.
And what are the Permissions I'm expecting to get? I'm wondering why MS didn't just let us pass the scopes as strings e.g. email, mail.read etc. I don't understand exactly what the Permissions are in this particular context.
I need help understanding (and accessing) the permission IDs in the "OAuth2Permissions property of the API's ServicePrincipal object".
The permission ID means the id of the Delegated permission of the API( i.e. oauth2Permissions defined in the API) you added in the client app registration.
For example, you created a multi-tenant client app in tenant A, you added the Mail.Read Delegated permission of Microsoft Graph, by default, there would also be a User.Read Delegated permission automatically, so there are two permissions totally in the API permissions of your client app.
Now, you want to use the custom app consent policy in tenant B, you want the user to consent the two permissions, then the -Permissions should be the id of the two permission defined in Microsoft Graph, to find it easily, just navigate to the client app in tenant A -> Manifest, then you can get the ids like below.
The complete command should be
New-AzureADMSPermissionGrantConditionSet `
-PolicyId "joy-custom-policy" `
-ConditionSetType "includes" `
-PermissionType "delegated" `
-ResourceApplication "00000003-0000-0000-c000-000000000000" `
-Permissions #("e1fe6dd8-ba31-4d61-89e7-88639da4683d","570282fd-fa5c-430d-a7fd-fc8dc98a9dca")
In another scenario, you use the custom API(created in tenant A) in the client app instead of a Microsoft API.
If so, you need to grant admin consent for the API App in tenant B first, otherwise you will get an error The app needs access to a service (\"api://tenantA/myapi\") that your organization (tenant B) has not subscribed to or enabled, or you can use the admin account to run New-AzureADServicePrincipal -AppId <appid of the API app> in tenant B, it will also work, after consent, the normal user will be able to consent the permission you defined in the policy.
Note: Sometimes, you may get an error This app may be risky like below.
This means Microsoft detects a risky end-user consent request, the request will require a step-up to admin consent instead, if you still want the user to consent the permission, you need to disable the risk-based step-up consent first, then the user will be able to consent the permission.
Here's an example for how you would get the permission IDs for three delegated permissions for Microsoft Graph, using Azure AD PowerShell:
# The appId for the client application
$clientAppId = "{client-app-id}"
# The claim values for the Microsoft Graph delegated permissions to include
$claimValues = #("User.Read", "Mail.Send", "User.ReadBasic.All")
# Get the service principal for Microsoft Graph
$resource = Get-AzureADServicePrincipal -Filter "servicePrincipalNames/any(n:n eq 'https://graph.microsoft.com')"
# Get the delegated permission IDs for the given claim values
$permissionIds = $resource.OAuth2Permissions `
| ? { $claimValues.Contains($_.Value) } | select -ExpandProperty Id
# Use these permission IDs in a condition set for a custom permission grant policy
New-AzureADMSPermissionGrantConditionSet `
-PolicyId "my-custom-policy" `
-ConditionSetType "includes" `
-ClientApplicationIds #($clientAppId) `
-PermissionType "delegated" `
-ResourceApplication $resource.AppId `
-Permissions $permissionIds

Authenticate for Azure REST API without login

I have a backend process that doesn't directly interact with the user. I want to access reservations associated with my Azure account but I'm having trouble with the authentication step. I was following the guide here and I managed to get the authentication request to work by calling
https://login.microsoftonline.com/{tenant-ID}/oauth2/token
as a POST with the following x-www-form-urlencoded body:
grant_type=client_credentials&
client_id={client-ID}&
client_secret={client-Secret}&
resource=http://myapp42
However, when I attempt to call:
https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/{order-ID}/reservations/{reservation-ID}?api-version=2019-04-01
with the bearer token I received during the authentication step, I get the following error message:
The access token has been obtained for wrong audience or resource 'http://myapp42'. It should exactly match with one of the allowed audiences 'https://management.core.windows.net/', 'https://management.core.windows.net', 'https://management.azure.com/', 'https://management.azure.com'
However, if I modify the resource on the request to be one of these, http://management.core.windows.net/ for instance, the authentication then fails with:
AADSTS500011: The resource principal named https%3A%2F%2Fmanagement.core.windows.net%2F was not found in the tenant named {tenant-ID}. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.\r\nTrace ID: b54cedea-3804-41cf-bd27-fcf0ed1c4700\r\nCorrelation ID: 2371d375-6c89-4f05-83c9-c4629b3340a8\r\nTimestamp: 2020-02-05 01:59:57Z
How do I authenticate so that I can then get my reservations without having to login?
Update:
The service principal has both the Owner and Contributor roles assigned.
Update 2:
Thanks to #Jim Xu, I was realized that I needed to refrain from url-encoding the URL. That allowed me to get the access token with a value of https://management.azure.com/ for the resource field. However, at this point, when I attempt to call the REST API with the resulting bearer token, I get the following error:
The client '{Object-ID}' with object id '{Object-ID}' does not have authorization to perform action 'Microsoft.Capacity/reservationOrders/reservations/read' over scope '/providers/Microsoft.Capacity/reservationOrders/{order-ID}/reservations/{reservation-ID}' or the scope is invalid. If access was recently granted, please refresh your credentials
Note: The object ID returned by this error is the one associated with the service principal.
Update 3:
I checked the reservation and it seems that the principal does not have a role in that reservation's access control. However, I also cannot assign the principal a role because it does not show when I search for principals during the role-assigning process.
If you want to call Azure Rest API to get the information of reservation Orders, you need to assign Owner\Contributor for the service principal.(the action needs Microsoft.Capacity/reservationOrders/read permission).
The steps are as below
Get access token
POST : https://login.microsoftonline.com/{tenant-ID}/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&
client_id={client-ID}&
client_secret={client-Secret}&
resource=https://management.azure.com/ or https://management.core.windows.net
Call the api
GET : https://management.azure.com/providers/Microsoft.Capacity/reservationOrders/{order-ID}/reservations/{reservation-ID}?api-version=2019-04-01
Authorization: Bearer <token>
For more details, please refer to the issue and the issue
update
If you have assigned role but you still cannot get access token, please try to encode your url.

Resources