Adding users with roles into app registration - azure-active-directory

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

Related

How to get the resourceId when granting an appRoleAssignment to a ServicePrincipal in Azure AD?

I am trying to Grant Admin Consent of a API in an Azure AD application through Graph API. I created the App, created its Client Secret, then created a Service Principal to which I want to add AppRoleAssignment.
The API call to do so requires three attributes in the body (Documentation)
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var appRoleAssignment = new AppRoleAssignment
{
PrincipalId = {Input the Service Principal Id},
ResourceId = {? Where to get this value?},
AppRoleId = {Input the App role of the API I added to my Azure AD App}
};
await graphClient.ServicePrincipals["{servicePrincipal-id}"].AppRoleAssignments
.Request()
.AddAsync(appRoleAssignment);
My question is where to get the ResourceId from? Knowing that this is different from one tenant to the other.
Please note that if I grant the admin consent manually, then run this API call
var appRoleAssignments = GraphAppClient.ServicePrincipals[servicePrincipalId].AppRoleAssignments.Request().GetAsync().Result;
Then revoke the consent, get the ResourceId from what the API returned, and then use it in the original call, the admin consent works fine.
The documentation for the appRoleAssignment resource type says the following about the resourceId property:
The unique identifier (id) for the resource service principal for which the assignment is made.
A good approach to find a service principal in a tenant is to search the servicePrincipals collection, filtering on the appId or servicePrincipalName properties.For example, to search for the Microsoft Graph service principal by its identifier URI:
GET https://graph.microsoft.com/v1.0/servicePrincipals
?$filter=servicePrincipalNames/any(n:n eq 'https://graph.microsoft.com')
Or to find it by its appId:
GET https://graph.microsoft.com/v1.0/servicePrincipals
?$filter=appId eq '00000003-0000-0000-c000-000000000000'
With the Microsoft Graph SDK for .NET, this would look something like this:
var r = await graphServiceClient.ServicePrincipals
.Request()
.Filter("appId eq '00000003-0000-0000-c000-000000000000'")
.GetAsync();
Using Microsoft Graph PowerShell, things look very similar:
$r = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"
Using the Azure portal, each app under "Enterprise apps" corresponds to a service principal, and the "Properties" page shows its object ID.
(Once you have the service principal, you can use its appRoles collection to see the list of app roles it publishes, often useful to get the app role's id, which you'll need for the appRoleId property.)
I ended up figuring it out. The resourceId of every set of permission you are trying to add is the objectId of the app in Entreprise Applications. It sounds very confusing, but if you are trying to add Graph API permissions, you need to go to enterprise applications, find GraphAPI, and then find its ObjectId. That is your resourceId.

Unable to add a Delegated Permission to an Azure AD application registration

I am new to Azure but have been messing around trying to get a feel for it. I have successfully used Azure AD to secure an API using application permissions. The typical example of creating an app role in the API registration that has an allowed member type of Application and then selecting and granting via API Permissions > Add Permission > Application Permissions of the client app registration.
Next I would like to implement OpenID Connect Authentication & Authorization where I grant a role to a user instead of the client web app. However the Delegated Permissions "tab" is not enabled. I have made sure that there is an app role created in the API as follows. I have also tried it with the app role with a allowedMemberTypes set to Users only but with the same disabled Delegated Permissions result.
Delegated Permissions Disabled:
"appRoles": [
{
"allowedMemberTypes": [
"User",
"Application"
],
"description": "Users and Applications with this role can consume the Pricing Model API",
"displayName": "Pricing Model Cosumer",
"id": "62d4b7d0-2e37-4a28-8918-098e3eabdc58",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "PricingModel.Consumer"
}
],
I have searched for hours and only found results pertaining to the Application Permissions option being disabled and the answer to this is always to verify that there is an application role to select in the specified API registration.
Is there something elsewhere that I may be missing? Is there a more appropriate way or place to ask this please let me know.
Delegated permissions are not defined in appRoles. You can add them instead in the "Expose an API" section of the app registration or in the oauth2Permissions.
To add the scope in the app registration:
Exposing delegated permissions (scopes)
Select Expose an API in the application registration.**
Select Add a scope.
If prompted, accept the proposed application ID URI (api://{clientId}) by selecting Save and Continue.
Specify these values:
Select Scope name and enter access_as_user.
Select Who can consent and make sure Admins and users is selected.
Select Admin consent display name and enter Access xxxservice as a user.
Select Admin consent description and enter Accesses the xxx web API as a user.
Select User consent display name and enter Access xxx as a user.
Select User consent description and enter Accesses the xxx web API as a user.
Keep the State value set to Enabled.
Select Add scope.
To define the delegated permissions in oauth2Permissions, see:
https://joonasw.net/view/defining-permissions-and-roles-in-aad

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:

Grant service principal access to application in other tenant

I have an Azure AD service principal in one tenant (OneTenant) that I would like to give access to an application in another tenant (OtherTenant).
The service principal in tenant OneTenant is a managed service identity for an Azure Logic App. So what I actually want is to call an API from my Logic App. This API is protected by an Azure AD application in OtherTenant.
The application in OtherTenant defines a number of roles and the service principal in OneTenant should have one of these roles so it can call the API.
I tried the following:
set the app in OtherTenant to multi-tenant
ran the following PS command to attempt to add the SP to a role in the app:
New-AzureADServiceAppRoleAssignment `
-ObjectId <object-id-of-sp-in-one-tenant> `
-Id <role-id> `
-PrincipalId <object-id-of-sp-in-one-tenant> `
-ResourceId <app-id-in-other-tenant>
(both logged in in OneTenant and OtherTenant)
This gives an error stating that either app-id-in-other-tenant or object-id-of-sp-in-one-tenant can not be found, depending on where I am signed in.
I also tried creating a Service Principal in OneTenant based on the app-id from OtherTenant In that case I get an error message: Authenticating principal does not have permission to instantiate multi-tenantapplications and there is not matching Applicationin the request tenant.
Ok, I finally got around to testing if the solution presented by Rohit Saigal works. It does point in the right direction but is not complete.
First step is to create a service principal in OneTenant that represents the application in OtherTenant. So while signed in to OneTenant, run the following script:
$spInOneTenant = New-AzureADServicePrincipal -AppId <app-id-in-other-tenant>
Next step is to run the New-AzureADServiceAppRoleAssignment cmdlet with the following parameters:
New-AzureADServiceAppRoleAssignment `
-Id <role-id> `
-ObjectId <object-id-of-sp-in-one-tenant> `
-PrincipalId <object-id-of-sp-in-one-tenant> `
-ResourceId $spInOneTenant.ObjectId
The trick is to use the object id of the service principal you created in the previous step as the ResourceId.
Taking the command as is from your question:
New-AzureADServiceAppRoleAssignment `
-ObjectId <object-id-of-sp-in-one-tenant> `
-Id <role-id> `
-PrincipalId <object-id-of-sp-in-one-tenant> `
-ResourceId <app-id-in-other-tenant>
Try changing the last parameter value i.e. ResourceId
Currently you're passing <app-id-in-other-tenant>
Replace that with <object-id-of-API-in-other-tenant>
The question/answers presented here were helpful, but yet it took me some time to work through the details and actually make it work, so allow me to elaborate some more on the above, as it might help others too.
Scenario
Two tenants:
Home Tenant.
Other Tenant.
One Azure App Service API app, with access managed by the Home Tenant.
One Logic app placed in a subscription in Other Tenant that need to securely access the API app in the Home Tenant.
Approach
Application registration
For the API app to delegate identity and access management to Azure AD an application is registered in the home tenant’s Azure Active Directory. The application is registered as a multi-tenant app.
You also need to create an app role (see documentation: How to: Add app roles in your application and receive them in the token), lets call it read.weather.
Configuration of Other Tenant and Logic App
To provide the Logic App access to the API app do this:
Enable a system assigned identity for the logic app - i.e. use Managed Identity. Note down the system assigned managed identity Object ID ({18a…}), you will need it in a minute.
Create a service principal for the application in the Other Tenant using this command, where appId is the appId of the application registered in Home Tenant (e.g. lets say it’s {1a3} here):
New-AzureADServicePrincipal -AppId {appId}
This command will output a json document which includes among other things an objectId for the service principal just created.
[... more json ...]
"objectId": "b08{…}",
[... more json...]
You should also see the appRoles, including the app role read.weather you just created, om the json output from the New-AzureADServicePrincipal command:
[... more json...]
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"description": "Read the weather.",
"displayName": "Read Weather",
"id": "46f{…}",
"isEnabled": true,
"value": "read.weather"
}
],
[... more json...]
To tie it all together make an app role assignment using the command:
New-AzureADServiceAppRoleAssignment -Id {app role ide} -ObjectId {system assigned identity object id} -PrincipalId {system assigned identity object id} -ResourceId {object id of service principal}
E.g. something like this:
New-AzureADServiceAppRoleAssignment -Id 46f… -ObjectId 18a… -PrincipalId 18a… -ResourceId b08…
Now we are ready to set up the HTTP request in the Logic App using the URI to the API app using Managed Identity for authentication.
Notice that the audience is needed and has the form: api://{appId}.
But wait…!
Does this mean that anyone could do this, if only they know the appId of your application registration, and wouldn’t this compromise the security of the API app?
Yes, it does, and yes indeed it could compromise the security of the API app.
If you look at the access token being created and used as bearer from the Logic App it is a valid access token, which contains all the necessary claims, including the app role(s). The access token is however issued by Other Tenant and not Home Tenant.
Therefore, if you have a multi tenanted application and you want to guard it against this scenario, then you could check the issuer (tid more likely) of the incoming access token calling the API and only accept it if the issuer is the Home Tenant, or you could make the application a single tenant app.
Or, you could require that the issuer matches a list of tenants that the API trusts.

Azure AD / Microsoft Graph Access Level Upgrade and Downgrade

Is there a way to upgrade and downgrade the Azure AD / Microsoft Graph access level?
For example, can a user signup with a web app only to login and later upgrade access to One Drive or downgrade back to login? I was looking for a way to unauthorize the user access and then reauthorize with the different set of permissions but couldn't find a way to unauthorize.
You can get incremental consent if you use the V2 endpoint: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-appmodel-v2-overview.
There you can specify which scopes you want to require when redirecting the user to login.
So you can require basic ones at the start, and then if they want to enable additional features/you release an update which requires additional permissions, you can add those quite easily.
As for the other direction, no.
Once a user has given consent for some permissions, the only way to undo the consent would be to delete the oauth2PermissionGrant object mapping the user to the application's service principal.
In case of an application permission, an appRoleAssignment would need to be deleted from the service principal.
So it's possible, but you will have to call Microsoft Graph API yourself.
You can get all permission grants via: https://graph.microsoft.com/beta/oauth2PermissionGrants and it returns grant objects like this:
{
"clientId": "e846195b-9b20-4001-ad84-5ab5de5531e6",
"consentType": "AllPrincipals",
"expiryTime": "2018-05-04T09:39:32.9697945Z",
"id": "WxlG6CCbAUCthFq13lUx5s7PF6398j5LkfWqCoLpQBI",
"principalId": null,
"resourceId": "ad17cfce-f2fd-4b3e-91f5-aa0a82e94012",
"scope": "User.Read Directory.AccessAsUser.All",
"startTime": "0001-01-01T00:00:00Z"
}
This one is actually the result of admin consent (consentType = AllPrincipals and principalId = null).
For regular user consent, principalId will be the id of the user.
clientId is the id of the service principal who was granted access, and resourceId is the target service principal.
You can also filter the results to a specific user for example: https://graph.microsoft.com/beta/oauth2PermissionGrants?$filter=principalId eq '73c38a25-23eb-44eb-bf63-4aa987b2ef19'
You can then update the grant to change the approved scopes by running a PATCH to https://graph.microsoft.com/beta/oauth2PermissionGrants/WxlG6CCbAUCthFq13lUx5s7PF6398j5LkfWqCoLpQBI with a body like:
{
"scope": "User.Read"
}
You can delete the grant entirely by running a DELETE on the same URL.

Resources