Search code examples
microsoft-graph-api

Trouble upgrading to the latest version of MsGraph


I have an MVC application which uses Ms Graph to connect to Active directory. It stopped working when I upgraded to .NET8 and updated my Nuget packages. I was able to comment out the parts relating to sending emails and uploading pictures although that's not ideal.

In the old version of MsGraph there is this code.

public GraphServiceClient GetAuthenticatedGraphClient(ClaimsIdentity userIdentity) => new GraphServiceClient(new DelegateAuthenticationProvider( async requestMessage => { // Get user's id for token cache. These links hard coded in sample application var identifier = userIdentity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value + "." + userIdentity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid")?.Value; //var identifier = userIdentity.FindFirst(Microsoft.AspNetCore.Identity.UserLoginInfo)?.Value + "." + userIdentity.FindFirst(ClaimTypes.NameIdentifier)?.Value;

              // Passing tenant ID to the sample auth provider to use as a cache key
              var accessToken = await _authProvider.GetUserAccessTokenAsync(identifier);



              // Append the access token to the request
              requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);



              // This header identifies the sample in the Microsoft Graph service. If extracting this code for your project please remove.
              //requestMessage.Headers.Add("SampleID", "aspnetcore-connect-sample");
              requestMessage.Headers.Add("MsGraphTest", "MsGraphTest");
          }));

}

I don't know how to use these instructions to replace it. They are in this document, but find it very unclear. https://github.com/microsoftgraph/msgraph-sdk-dotnet/blob/dev/docs/upgrade-to-v5.md?plain=1

I think this is the relevant part.

Authentication

The GraphServiceClient constructor accepts instances of TokenCredential from Azure.Identity similar to previous library version as follows


var interactiveBrowserCredential = new InteractiveBrowserCredential(interactiveBrowserCredentialOptions);

var graphServiceClient = new GraphServiceClient(interactiveBrowserCredential);

In place of the DelegateAuthenticationProvider, custom authentication flows can be done creating an implementation of IAccessTokenProvider, and using with the BaseBearerTokenAuthenticationProvider from the Kiota abstractions as follows


public class TokenProvider : IAccessTokenProvider

{

    public Task<string> GetAuthorizationTokenAsync(Uri uri, Dictionary<string, object> additionalAuthenticationContext = default,

        CancellationToken cancellationToken = default)

    {

        var token = "token";

        // get the token and return it in your own way

        return Task.FromResult(token);

    }



    public AllowedHostsValidator AllowedHostsValidator { get; }

}

Then create the GraphServiceClient as follows


var authenticationProvider = new BaseBearerTokenAuthenticationProvider(new TokenProvider());

var graphServiceClient = new GraphServiceClient(authenticationProvider);

Authentication using the graph client is no longer handled in the HttpClient middleware pipeline. Therefore, using the GraphServiceClient(httpClient) constructor will assume that the passed httpClient has already been configured to handle authentication in its pipeline.

Otherwise, passing an instance of IAuthenticationProvider to the constructor (GraphServiceClient(httpClient, authenticationProvider)) will make authenticated requests if the passed HttpClient is not already configured.

Use of RequestInformation from Kiota in place of IBaseRequest

The RequestInformation class is now used to represent requests in the SDK and the IBaseRequest is dropped. Using the fluent API, you can always get an instance of the RequestInformation as follows.


// Get the requestInformation to make a GET request

var requestInformation = graphServiceClient

                         .DirectoryObjects

                         .ToGetRequestInformation();

Solution

  • Glad to hear that the tutorial is working. If you are specifically targeting an app in the dev environment, you must ensure that the app is registered in the dev environment and thus reference the clientID and the TenantID of the app within dev environment. Ensure that the same is updated on your code.