Failing to update Azure AD group's display name from C# code using MS Graph API

200 Views Asked by At

I am trying to update the displayName of an EntraID (Azure AD) group from my C# code.

I have an Azure App registration that has (delegated) permissions for MS Graph - Group.ReadWrite.All, and I have applied admin consent on this for my entire tenant.

Using the Microsoft.Identity.Client, I can easily run my .NET 6.0 console app and using the PublicClientApplication, I can get a valid access token for that scope, for the currently logged in user (interactively - with a standard M365 login prompt dialog). I can also query MS Graph to get me the Id of the group I'm interested in - so far, so good.

But the heart of my task - updating the displayName of that EntraID group, fails with a http 403 - forbidden error - even though my app registration clearly has the Group.ReadWrite.All permission, and the access token I get also lists that scope (when I decode it at https://jwt.ms).

This is the code to update the display name of my group:

public class GroupHandler
{
    private HttpClient _client;

    public GroupHandler(string graphBaseUrl, string accessToken)
    {
        _client = new HttpClient();
        _client.BaseAddress = new Uri(graphBaseUrl);    // this is https://graph.microsoft.com
        _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
    }

    public async Task UpdateGroupDisplayName(string groupId, string displayName)
    {
        string requestUrl = $"/v1.0/groups/{groupId}";

        PatchObject patchObj = new PatchObject { displayName = displayName };
        JsonContent content = JsonContent.Create(patchObj, new MediaTypeHeaderValue("application/json"));

        var response = await _client.PatchAsync(requestUrl, content);

        if (response.IsSuccessStatusCode)
        {
            Console.WriteLine($"Group has been successfully renamed to '{displayName}'");
        }
        else
        {
            Console.WriteLine($"ERROR: {response.StatusCode} - {response.ReasonPhrase}");
        }
    }
}

// this is the class to hold the new display name, to be serialized to JSON for the PATCH call
public class PatchObject
{
    public string displayName { get; set; }
}

Any ideas? I'm a bit at a loss, since my app registration has the necessary permission, they have admin consent, the token also shows that scope - so why would it still fail?

1

There are 1 best solutions below

0
On

I agree with @user2250152, the signed-in user should have extra role like Groups Administrator along with Group.ReadWrite.All delegated permission while using interactive flows.

I have one Azure AD group named SriGroup in my tenant with below properties:

enter image description here

When I tried to rename this group by signing in with user having no directory roles and granting only Group.ReadWrite.All delegated permission in application, I too got same error as below:

Sample code:

using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Graph.Models;
using Microsoft.Graph.Models.ODataErrors;

var scopes = new[] { "Group.ReadWrite.All" };

var tenantId = "tenantId";
var clientId = "appId";

var options = new InteractiveBrowserCredentialOptions
{
    TenantId = tenantId,
    ClientId = clientId,
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
    RedirectUri = new Uri("http://localhost"),
};

var interactiveCredential = new InteractiveBrowserCredential(options);

var graphClient = new GraphServiceClient(interactiveCredential, scopes);

var requestBody = new Group
{
    DisplayName = "Sri Group Nov",
};

try
{
    await graphClient.Groups["groupId"].PatchAsync(requestBody);
    Console.WriteLine($"Group has been successfully renamed");

}

catch (ODataError odataError)
{
    Console.WriteLine(odataError.Error.Code);
    Console.WriteLine(odataError.Error.Message);
    throw;
}

Response:

enter image description here

To resolve the error, I assigned Groups Administrator role to that user in my tenant like this:

Go to Azure Portal -> Microsoft Entra ID -> Roles and administrators -> All roles -> Select Groups Administrator -> Add assignments

enter image description here

When I ran the code again by signing in with user having Groups Administrator role, I got the response like this:

using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Graph.Models;
using Microsoft.Graph.Models.ODataErrors;

var scopes = new[] { "Group.ReadWrite.All" };

var tenantId = "tenantId";
var clientId = "appId";

var options = new InteractiveBrowserCredentialOptions
{
    TenantId = tenantId,
    ClientId = clientId,
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
    RedirectUri = new Uri("http://localhost"),
};

var interactiveCredential = new InteractiveBrowserCredential(options);

var graphClient = new GraphServiceClient(interactiveCredential, scopes);

var requestBody = new Group
{
    DisplayName = "Sri Group Nov",
};

try
{
    await graphClient.Groups["groupId"].PatchAsync(requestBody);
    Console.WriteLine($"Group has been successfully renamed");

}

catch (ODataError odataError)
{
    Console.WriteLine(odataError.Error.Code);
    Console.WriteLine(odataError.Error.Message);
    throw;
}

Response:

enter image description here

To confirm that, I checked the same in Portal where group name updated successfully as below:

enter image description here

Alternatively, you can also make use of client credentials flow by granting Group.ReadWrite.All permission of Application type that does not require any extra roles.