简体   繁体   中英

Calling Microsoft Graph API using user context/user token C#

I have a web application where user logins using the approach defined in this sample .

Now I want to call Microsoft Graph for this User. I have gone through many documents and it's very confusing how this should be done. This is what I have tried. I am not sure how to get the access token for this user.

//not sure about this
var token = await GetAccessToken();

var client = new GraphServiceClient(
    new DelegateAuthenticationProvider(
        requestMessage =>
        {
            requestMessage.Headers.Authorization =
                new AuthenticationHeaderValue("Bearer", token);

            return Task.FromResult(0);
        }));

var result = await client
    .Me
    .Request()
    .GetAsync();

As per this documentation , I need to use the Confidential Client Flow, but I am not sure if I need to use the Authorization Code flow or On-Behalf. I don't have access to the Authorization Code because of the approach I followed here .

ConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithTenantId(tenantId)
    .WithCertificate(clientCertificate)
    .Build();

Can someone please guide me on how to get the access token for the User? Should I be using Authorization Code flow or On-Behalf?

If you are following the sample listed above, you are on the right track. Following the tutorial, it shows to how call Microsoft Graph /me endpoint on behalf of the signed-in user. In this sample, the complexities of the ASP.NET Core middleware and MSAL.Net are encapsulated in the Microsoft.Identity.Web section of the tutorial.

You should already have a Web App registered in the Azure Portal. Now that you'll be calling Microsoft Graph, you'll need to register a certificate or secret for the Web App. Then in API permissions, ensure the Microsoft APIs tab is selected and choose the ones you want for Microsoft Graph.

Then, continue following the tutorial to enable MSAL to hook-up to the OpenID Connect events and redeem the authorization code obtained by the ASP.NET Core middleware. Once a token is received, MSAL will save it into a token cache (there is tutorial for this as well).

Keep following the tutorial and you'll add the GraphServiceClientFactory.cs which returns a GraphServiceClient . When it receives an access token for Microsoft Graph, it will make requests to Graph sending the access token in the header. The code is here :

public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
      string accessToken = await acquireAccessToken.Invoke();

      // Append the access token to the request.
      request.Headers.Authorization = new AuthenticationHeaderValue(
      Infrastructure.Constants.BearerAuthorizationScheme, 
      accessToken);
}

There is a bit more set-up to do, but follow the tutorial and you should be able to acquire a token and then use it to call Microsoft Graph.

Note: you will need to reference your project with Microsoft.Graph

First, you will need a function to request for an access token

async Task<string> Post(string uri, Dictionary<string, string> parameters)
{
    HttpResponseMessage response = null;
    try
    {
        using (var httpClient = new HttpClient() { Timeout = TimeSpan.FromSeconds(30) })
        {
            response = await httpClient.PostAsync(uri, new FormUrlEncodedContent(parameters));
            if (!response.IsSuccessStatusCode)
                throw new Exception("post request failed.");

            var content = response.Content.ReadAsStringAsync().Result;
            if (string.IsNullOrWhiteSpace(content))
                throw new Exception("empty response received.");

            return content;
        }
    }
    catch (Exception e)
    {
        throw new Exception(error);
    }
}

Then you will need a model to handle the response from the web request

public class TokenRequest
{
    [JsonProperty("token_type")]
    public string TokenType { get; set; }

    [JsonProperty("access_token")]
    public string AccessToken { get; set; }
}

Then you will need a function to extract the data from the web request

TokenRequest GetAccessToken()
{
    // request for access token.
    var parameters = new Dictionary<string, string>();
    parameters.Add("client_id", "YOUR CLIENT ID");
    parameters.Add("client_secret", "YOUR CLIENT SECRET");
    parameters.Add("scope", "https://graph.microsoft.com/.default");
    parameters.Add("grant_type", "client_credentials");

    var response = Post(
        $"https://login.microsoftonline.com/{YOUR TENANT ID}/oauth2/v2.0/token",
        parameters).Result;

    return JsonConvert.DeserializeObject<TokenRequest>(response);
}

Then request for an authenticated graph api client

GraphServiceClient GetClient()
{
    var tokenRequest = GetAccessToken();
    var graphClient = new GraphServiceClient(
        new DelegateAuthenticationProvider(
            async (requestMessage) => {
                await Task.Run(() => {
                    requestMessage.Headers.Authorization = new AuthenticationHeaderValue(
                        tokenRequest.TokenType,
                        tokenRequest.AccessToken);

                    requestMessage.Headers.Add("Prefer", "outlook.timezone=\"" + TimeZoneInfo.Local.Id + "\"");
                });
            }));

    return graphClient;
}

Then using the client, you can now perform your queries

var graphClient = GetClient();
var user = await graphClient
    .Users["SOME EMAIL ADDRESS HERE"]
    .Request()
    .GetAsync();

Very important: you also have to make sure you have the proper api permissions on your active directory app registration. Without it, you will only get a request denied response from the graph api.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM