I'm using the graph API to retrieve user images and SharePoint list items and authenticating with a managed service identity. I was successfully able to add the required permissions to my service identity using powershell.
<#
ERRORS OUT BUT WORKS. YOU CAN VALIDATE BY USING THE GRAPH EXPLORER TO CALL:
https://graph.microsoft.com/beta/servicePrincipals/{msiObjectId}/appRoleAssignedTo
NOTE: Get-AzureADServiceAppRoleAssignedTo DOES NOT WORK, MUST USE GRAPH EXPLORER FOR VALIDATION
#>
Connect-AzureAD
$msiObjectId = "12345678-1234-1234-1234-123456789101"
$app_name = "Microsoft Graph"
$role_names = @("Sites.Read.All", "User.Read.All", "Directory.Read.All")
$sp = Get-AzureADServicePrincipal -Filter "displayName eq '$app_name'"
$role_names | foreach {
$role_name = $_
$appRole = $sp.AppRoles | Where-Object { ($_.DisplayName -eq $role_name) -or ($_.Value -eq $role_name) }
New-AzureADServiceAppRoleAssignment -ObjectId $msiObjectId -PrincipalId $msiObjectId -ResourceId $sp.ObjectId -Id $appRole.Id
}
Disconnect-AzureAD
This errors but adds the permissions and works perfectly when I publish the app to the azure service assigned to the service identity.
I'm using Microsoft.Azure.Services.AppAuthentication to retrieve the token and make the calls.
using Microsoft.Azure.Services.AppAuthentication;
...
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await new AzureServiceTokenProvider().GetAccessTokenAsync("00000003-0000-0000-c000-000000000000"));
...
The problem is in local development it falls back to my credentials. This succesfully gets a token that has some basic graph access such as /me and /user basic but when I try to retrieve a list or user image I get the following error:
{
"error": {
"code": "accessDenied",
"message": "The caller does not have permission to perform the action.",
"innerError": {
"request-id": "55555555-1234-1234-1234-123456789101",
"date": "2019-06-12T17:05:31"
}
}
}
I've tried using my own object ID in place of $msiObjectId
in the powershell code exactly as it is and also tried changing New-AzureADServiceAppRoleAssignment
to New-AzureADUserAppRoleAssignment
but neither worked. I've also tried everything I could in the UI and found no way to add the permissions and tried https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize?client_id=00000003-0000-0000-c000-000000000000&scope=offline_access%20User.Read.All%20Sites.Read.All
which gives me an error about no reply url and also doesn't work.
I'm thinking I may need to add some delegate permissions for my account in place of the application role assignments but I can't find anyway to do that. I am able to see the permissions using $sp.Oauth2Permissions
but can't figure out a way to grant myself those permissions.
Is this possible to do and if so, how?
Basically, I need my credentials (without an app) to have at least "Sites.Read.All" and "User.Read.All" access to Microsoft Graph (GraphAggregatorService) when using new AzureServiceTokenProvider().GetAccessTokenAsync())
I hit this problem when making my samples of using the AzureServiceTokenProvider locally to call my own APIs. The issue is as you have noticed, the fact that the token acquired locally is a delegated token. In Azure, it is an app-only token.
You cannot assign app permissions to a user, unless the appRoles allowed member types included both User and Application. And that would be quite a weird thing to do. MS Graph API doesn't do that.
So you need an app-only token.
Locally, your best bet might be to use MSAL to acquire a token with client credentials, and use AzureServiceTokenProvider only in Azure. Then you'll get a token that is similar to what you get in Azure, with app permissions and such.