Azure AD / Microsoft Graph Access Level Upgrade and Downgrade - azure-active-directory

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.

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

Microsoft OAuth authorization for specific user roles

I have to limit which users can access an Azure App. For now, only Global Admins can access using this link:
login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=client_id_goes_here&scope=user.read.all&response_type=code&redirect_uri=https://myredirectbacklink.com/aad/auth&response_mode=query&state=portal&prompt=consent
After redirect back I get Token using
https://login.microsoftonline.com/common/oauth2/v2.0/token and the query contains the same scope as the authorized link.
The flow of the app is the same as documented in Microsoft identity platform and OAuth 2.0 authorization code flow.
My problem is that client wants to allow Billing Admins to access their app. I went through all Graph Permission Scopes, but could not find any related to Billing Admin.
My knowledge of Microsoft's authorization is somewhat limited. I do know that limitations are done by scope. But if it's just link change or is it in Authentication App in Azure (there is one but I don't know how it's related to actual login permissions).
Should I look in a different direction or is it just simply changing the link? Microsoft's documentation didn't help a lot because it's mostly about calendars and other simple stuff.
Careful, requesting a permission that normally requires admin consent and causing the user consent prompt is not the proper way to ensure the user signing in is actually an admin. A non-admin user could simply modify the URL to scope=User.ReadBasic.All and remove prompt=consent. If the user is allowed to consent for User.ReadBasic.All (which is true in many organizations), they'd be able to continue the sign-in. (Or if the organization had granted admin consent for "User.Read.All", the non-admin user would only need to remove prompt=consent.)
If you need to ensure the user is an administrator, you need to explicitly check for directory role assignments.
You can choose from one of three different ways to do this:
You can configure your app to receive the wids claim, which will include the role template IDs of the directory roles for which the user has an active assignment. This is probably the simplest approach.
Using the Azure portal, you can do this under App registrations > (choose your app) > Token configuration > + Add groups claim. You must include "Directory roles" in your selection:
Another option is to a Microsoft Graph API request to check which of a given list of directory roles the user has been assigned:
POST https://graph.microsoft.com/v1.0/me/checkMemberObjects
Content-type: application/json
{
"ids": [
"fdd7a751-b60b-444a-984c-02652fe8fa1c",
"b0f54661-2d74-4c50-afa3-1ec803f12efe"
]
}
A third option is to make a Microsoft Graph API request to list the directory role assignments granted to the user:
GET https://graph.microsoft.com/beta/roleManagement/directory/roleAssignments
?$filter=principalId eq '{id}'
All three of these approaches involve using directory role template IDs to identify the directory role you are checking for. They're all listed here: https://learn.microsoft.com/azure/active-directory/roles/permissions-reference
Some examples you may be interested in:
Application administrator: 9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3
Cloud application administrator: 158c047a-c907-4556-b7ef-446551a6b5f7
Global administrator: fdd7a751-b60b-444a-984c-02652fe8fa1c
Privileged role administrator: e8611ab8-c189-46e8-94e1-60213ab1f814
Billing administrator: b0f54661-2d74-4c50-afa3-1ec803f12efe
(I included the first four because those are the directory roles which would, by default, be allowed to grant consent for User.Read.All.)
If someone needs solution and uses php:
You can use https://github.com/microsoftgraph/msgraph-sdk-php
$accessToken = 'token from redirect back, called access_token';
$body = [
"ids" => [
"fdd7a751-b60b-444a-984c-02652fe8fa1c",
"b0f54661-2d74-4c50-afa3-1ec803f12efe"
]
];
$graph = new Graph();
$graph->setAccessToken($accessToken);
$user = $graph->createRequest("post", "/me/checkMemberObjects")
->attachBody($body)
->execute();

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

To-Do API: The Service is not available

When calling the MS Graph API on the endpoint https://graph.microsoft.com/beta/me/todo/lists, I get the following result (same when using v1.0 instead of beta):
{
"error": {
"code": "UnknownError",
"message": "The service is unavailable.",
"innerError": {
"date": "2021-01-05T18:36:43",
"request-id": "a4549f79-399a-401b-84eb-cc2f8f6197c8",
"client-request-id": "e07b23bb-60bd-be9b-39db-60953ff42844"
}
}
}
Permission Tasks.ReadWrite is consented and the authenticated user account is a personal account (aka Microsoft Account). With a "Work or school account", the API works as expected.
As of the documentation, this endpoint should be fully available in v1.0 and beta versions but it obviously is not - or I do something wrong. Any suggestions?
You can try to use graph-explorer to log in to your personal Microsoft account and call the api. I just tested it with this tool and it did work for me. (Don't forget to add Tasks.ReadWrite permission and consent)
Another method is to add your personal Microsoft account as a guest user to the Azure tenant (note: guest users need administrator role to call the api), then grant Tasks.ReadWrite delegation permissions to the application, and then use the auth code flow Obtain an access token. This requires you to log in to your personal Microsoft account to obtain an authorization code, and then use the authorization code to redeem an access token.

Azure AD & Graph API Permission

I have a variety of graph permissions assigned to different web apps in Azure. Is there any way in which I can map these graph permissions back to Azure AD roles and identify which role is the permission assigned to? I need this to implement access control based on the signed-in user
Graph permissions are granted for Azure AD app. Azure AD role is to manage Azure AD rather than API permission. There is no mapping between them.
What you are looking for is appRole.
"appRoles": [
{
"allowedMemberTypes": [
"User"
],
"displayName": "Writer",
"id": "d1c2ade8-98f8-45fd-aa4a-6d06b947c66f",
"isEnabled": true,
"description": "Writers Have the ability to create tasks.",
"value": "{the custom role name}"
}
]
A sample for your reference: Authorization in a web app using Azure AD application roles & role claims.
Update
You need to add the needed Graph permissions in Azure AD APP and then control the permissions in your code.
We assume you have assigned a custom role in an Azure AD app and added a user to this role.
When a user signs in, a token which includes the role claim will be returned.
You can judge the user's role in the code. If it matches a custom appRole, he is allowed to perform an operation, such as user-invite-all . If the user does not match any of the appRoles, he does not have permission to perform any operations.
[HttpPost]
[Authorize(Roles = "Admin, Writer, Approver")]
public ActionResult TaskSubmit(FormCollection formCollection)
{
if (User.IsInRole("Admin") || User.IsInRole("Writer"))
//do something such as inviting others.
{
Please dig deeper into the sample code I shared above.
PS: Note that I have modified the value in "appRoles" in my previous answer.

Resources