Search code examples
c#.net-coremicrosoft-graph-sdks

How to authenticate Microsoft Graph using client credentials and an access token in C#?


We have a .net core web application that uses Microsoft Graph to access some files in a SharePoint document library. Pretty basic. We have set up the Sites.Selected application permissions on the registration. From what I understand, client credentials is the way to authenticate with the application against Microsoft Graph. The examples I have found show the following code:

// The client credentials flow requires that you request the
// /.default scope, and preconfigure your permissions on the
// app registration in Azure. An administrator must grant consent
// to those permissions beforehand.
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 TokenCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};

// https://learn.microsoft.com/dotnet/api/azure.identity.clientsecretcredential
var clientSecretCredential = new ClientSecretCredential(
    tenantId, clientId, clientSecret, options);

var graphClient = new GraphServiceClient(clientSecretCredential, scopes);

But when I use this code, I get an error: "Either scp or roles claim need to be present in the token."

I have figured out how to get an access token, but I can't figure out how to apply the access token to the above code. Is there a way to do this, or am I on the wrong track here all together?

EDIT: I have gotten a few questions about the application registration, so I'll add the info in order to clear things up.

The app has been registered as a multi-tenant app, and an Application Permission has been set for "Sites.Selected". Additionally, the commands have been run in powershell to assign the correct access to the SharePoint site, using the app ID and the site ID/Site Name. Additional commands were run to confirm the correct access was applied.


Solution

  • Turns out I didn't need to actually generate an access token. This was the solution that worked for me.

    public GraphServiceClient InitializeGraphClientAsync()
    {
        var MyConfig = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
    
        // Values from app registration
        var clientId = MyConfig.GetValue<string>("AzureAd:ClientId");
        var clientSecret = MyConfig.GetValue<string>("AzureAd:ClientSecret");
    
        //var scopes = new[] { "https://graph.microsoft.com/.default" };
        var scopes = new[] { ".default" };
    
        // Multi-tenant apps can use "common",
        // single-tenant apps must use the tenant ID from the Azure portal
        var tenantId = MyConfig.GetValue<string>("AzureAd:TenantId");
    
        // https://learn.microsoft.com/dotnet/api/azure.identity.clientsecretcredential
        var clientSecretCredential = new ClientSecretCredential(
            tenantId, clientId, clientSecret);
    
        var graphClient = new GraphServiceClient(clientSecretCredential,scopes);
    
        return graphClient;
    }