Search code examples
c#azuremicrosoft-graph-apimicrosoft-entra-id

How to Assign Role to New User with Graph API


I have a React App and .NET 8 Web API with their own app registrations in an MS Entra External ID tenant. Authentication is done using msal-react and I'm using Microsoft.Identity.Web on the backend.

I'd like to programmatically assign a role to a user after they've successfully registered as certain Web API endpoints require this role for authz. I've been looking at MS documentation but am a little stuck on the overall picture of how to implement it.

This MS article shows the following code to send a request to assign the role via Graph API:

// Dependencies
using Microsoft.Graph.Models;

var requestBody = new AppRoleAssignment
{
    PrincipalId = Guid.Parse("cde330e5-2150-4c11-9c5b-14bfdc948c79"),
    ResourceId = Guid.Parse("8e881353-1735-45af-af21-ee1344582a4d"),
    AppRoleId = Guid.Parse("00000000-0000-0000-0000-000000000000"),
};

// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.Users["{user-id}"].AppRoleAssignments.PostAsync(requestBody);

Based on that I have to create a Graph Client using OBO that I found in this MS article it looks like this:

var scopes = new[] { "https://graph.microsoft.com/.default" };

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";

// Values from app registration
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";

// using Azure.Identity;
var options = new OnBehalfOfCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};

// This is the incoming token to exchange using on-behalf-of flow
var oboToken = "JWT_TOKEN_TO_EXCHANGE";

var onBehalfOfCredential = new OnBehalfOfCredential(
    tenantId, clientId, clientSecret, oboToken, options);

var graphClient = new GraphServiceClient(onBehalfOfCredential, scopes);

So, in my Web API code I need to get the PrincipalId of the user, ResourceId of the Web API (where the App Roles were created), and the AppRoleId to be able to send the request.

I haven't used Graph API before so I wanted to check that if this is the correct way of going about it such that the access token for the user gets updated/returned with the new role added to the roles claim to be used to successfully hit the endpoints requiring said role when the user makes a request to it.

Does this look correct and/or am I missing anything? I believe I may need to add another Graph API scope to the second code snippet but any guidance is helpful as I navigate this interesting world of MS Graph.


Solution

  • Your approach is correct for adding application roles to users. For the second snippet you will need additional scopes as described in the documentation. AppRoleAssignment.ReadWrite.All and Application.Read.All would be the least privileged combination.

    Note this applies if you are calling Graph API on behalf of a user; if you wanted to do this with only application credentials, it'd require the application permissions with same names (instead of delegated permissions aka scopes).

    Make sure the ResourceId matches the object ID of the target API service principal.