0

I have created a WebAPI using .NET 5 using Azure AD for authentication of the user. I am using Postman to generate the Access Token and the WebAPI Works when passing Access Token as Bearer.

I want to call Graph API to get the user Calendar & Profile using the Access Token but unable to do so. I have followed few articles mentioned below with no luck.

Invalid Authentication Token error when using the Access Token to call /me Graph API enter image description here

App registration to use My Org Only. I have added Delegated permissions to Graph API.

enter image description here

Created A custom scope using Expose An API as the WebAPI Was throwing Signature Invalid Error.

My WebAPI Configure Services in StartUp.cs Code:

services.AddMicrosoftIdentityWebApiAuthentication(Configuration);

My AppSettings.json

  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "<Domain",
    "ClientId": "<ClientId>",
    "TenantId": "<TenantId>"
  },

I have tried to follow couple of articles which suggest On Behalf Of Flow

https://joonasw.net/view/azure-ad-on-behalf-of-aspnet-core

Struggle with MS Graph and asp.net Core API

I am lost any help is much appreciated.

EDIT1:

I tried Implementing the solution suggested by Farid. The postman output was returning HTML Response to Sign In. It is a ASP.NET Core 5 WebAPI so I changed the ConfigureServices code to below:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)              
         .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"))
         .EnableTokenAcquisitionToCallDownstreamApi()
         .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
         .AddInMemoryTokenCaches();

I receive the following Error.

System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).
   at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
   at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Update:

I was able to resolve the error by using below code:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)                 .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()                    .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();

I am able to read my profile but not able to obtain Calendar Items. It could be due to Admin Consent Requirement.

10
  • 1
    Would you kindly have a try the solution and let me know if that works exactly. Commented Sep 2, 2021 at 1:03
  • @MdFaridUddinKiron: Thanks a lot for helping out and providing the solution. I am trying it and will let you know if it worked. Commented Sep 2, 2021 at 9:42
  • My pleasure, keep me updated, even you requires further assistance on this. Commented Sep 3, 2021 at 1:37
  • Hello, is there anything else that I can assist on this? Commented Sep 7, 2021 at 1:24
  • @MdFaridUddinKiron It's a .NET 5 WebAPI I am building and .AddMicrosoftIdentityWebApp doesn't seem to be available. Any particular package needs to be installed? Commented Sep 7, 2021 at 7:52

1 Answer 1

2

As per your given information it seems your token has expired, so firstly try to regenerate that, additionally, you have added Delegated permissions that's fine but I doubt you haven added the grant admin consent after adding Graph API permission. So its mandatory and please double check that. See the below screen capture. Please follow the below steps to get token and user info using Microsoft Graph API

Grant Admin Consent:

enter image description here

Token Aquisition Example:

Check the appsettings.json it should be like below:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "yourdemain.onmicrosoft.com",
    "TenantId": "",
    "ClientId": "",
    "ClientSecret": "",
    "ClientCertificates": [
    ],
    "CallbackPath": "/signin-oidc"
  },
  "DownstreamApi": {

    "BaseUrl": "https://graph.microsoft.com/v1.0",
    "Scopes": "https://graph.microsoft.com/.default"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Startup.cs

  public void ConfigureServices(IServiceCollection services)
        {
            string[] initialScopes = Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');

            services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
                .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
                .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
                .AddInMemoryTokenCaches();

            services.AddControllersWithViews(options =>
            {
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            });
            services.AddRazorPages()
                    .AddMicrosoftIdentityUI();
        }

Note: You can ignore below two service from the ConfigureServices under startup.cs .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) because I am using Graph API SDK and reading scope from appsettings.json so in the sample I am using local scope for your test case. So its not required or upto you.

Controller Action:

public async Task<object> GetUserInfoFromGraphAPI()
        {

            try
            {

                //Initialize on behalf of user token aquisition service

                var _tokenAcquisition = this.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>() as ITokenAcquisition;

                //define the scope
                string[] scopes = new string[] { "https://graph.microsoft.com/.default" };

                //Getting token from Azure Active Directory
                string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes);

                //Request Grap API end point
                HttpClient _client = new HttpClient();
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, string.Format("https://graph.microsoft.com/v1.0/me"));

                //Passing Token For this Request
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                HttpResponseMessage response = await _client.SendAsync(request);

                //Get User into from grpah API
                dynamic userInfo = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());


                return userInfo;
            }
            catch (Exception ex)
            {

                throw;
            }

        }

Output:

enter image description here

Note: For complete solution please visit the GitHub Link

Hope it will help you to achive your goal.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.