Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Status Code: 0 Microsoft.Graph.ServiceException: Code: generalException #1602

Closed
JRawlins737 opened this issue Jan 25, 2022 · 12 comments · Fixed by #1613
Closed

Status Code: 0 Microsoft.Graph.ServiceException: Code: generalException #1602

JRawlins737 opened this issue Jan 25, 2022 · 12 comments · Fixed by #1613
Labels
bug Something isn't working regression regression between Microsoft Identity Web versions
Milestone

Comments

@JRawlins737
Copy link

JRawlins737 commented Jan 25, 2022

Upgraded Microsoft.Identity.Web from Version 1.21.1. (where is has been working just fine for many weeks) to 1.22.0 then 1.22.1 resulting in the same error. Rolling back to 1.21.1 fixes the issue... Also update TargetFramework from .Net 5 to 6 but still errors out.

Error occurred during the first debug after NuGet updates of Microsoft.Identity.Web and Microsoft.Identity.Web.MicrosoftGraph when the following code was executed in a Web API project.

await _graphServiceClient.Me.CheckMemberGroups(groupIds).Request().PostAsync();

groupId's is of type List<String> and contained 2 GUID's that map to 2 groups.

The stack trace of the failure is here:

Status Code: 0
Microsoft.Graph.ServiceException: Code: generalException
Message: An error occurred sending the request.
 
---> System.ArgumentNullException: Value cannot be null. (Parameter 'configuration')
   at Microsoft.Extensions.Configuration.ConfigurationBinder.Bind(IConfiguration configuration, Object instance, Action`1 configureOptions)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.Bind(IConfiguration configuration, Object instance)
   at Microsoft.Identity.Web.Internal.WebApiBuilders.<>c__DisplayClass0_0.<EnableTokenAcquisition>b__0(ConfidentialClientApplicationOptions ccaOptions, IOptionsMonitor`1 mergedOptionsMonitor)
   at Microsoft.Extensions.Options.ConfigureNamedOptions`2.Configure(String name, TOptions options)
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
   at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass10_0.<Get>b__0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.get_Value()
   at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
   at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
   at Microsoft.Identity.Web.TokenAcquisition.GetOptions(String authenticationScheme)
   at Microsoft.Identity.Web.TokenAcquisition.GetAuthenticationResultForUserAsync(IEnumerable`1 scopes, String authenticationScheme, String tenantId, String userFlow, ClaimsPrincipal user, TokenAcquisitionOptions tokenAcquisitionOptions)
   at Microsoft.Identity.Web.TokenAcquisitionAuthenticationProvider.AuthenticateRequestAsync(HttpRequestMessage request)
   at Microsoft.Graph.AuthenticationHandler.SendAsync(HttpRequestMessage httpRequestMessage, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at Microsoft.Graph.HttpProvider.SendRequestAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at Microsoft.Graph.HttpProvider.SendRequestAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
   at Microsoft.Graph.HttpProvider.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
   at Microsoft.Graph.BaseRequest.SendRequestAsync(Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption)
   at Microsoft.Graph.BaseRequest.SendAsync[T](Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption)
   at Microsoft.Graph.DirectoryObjectCheckMemberGroupsRequest.PostAsync(CancellationToken cancellationToken)
   at Managers.Implementation.AgentManager.GetPermissionGroups(ClaimsPrincipal identity) in D:\Development\..\AgentManager.cs:line 148
   at Managers.Implementation.AgentManager.GetToken(ClaimsPrincipal identity) in D:\Development\..\AgentManager.cs:line 76
   at api.identity.Controllers.AgentController.GetToken() in D:\Development\..\AgentController.cs:line 35
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   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)

Expected behavior
The method would normally return a list groups that the current user is a member of..

Actual behavior
Throws exception above..

@jmprieur jmprieur added regression regression between Microsoft Identity Web versions investigate more info needed and removed investigate labels Jan 25, 2022
@jmprieur
Copy link
Collaborator

@JRawlins737

  • Is it in a web app or a web API?
  • would you have some repro steps? or a repo with which we could debug?

@JRawlins737
Copy link
Author

This is a Web API project. Sorry, no public repo :(

Usual configuration in the startup
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(
options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidAudiences = Configuration.GetValue("AZUREAD_AUDIENCE").Split(new[] { CONST_VERTICAL_BAR }, StringSplitOptions.RemoveEmptyEntries)
};
},
identityOptions =>
{
identityOptions.Instance = Configuration.GetValue("AZUREAD_INSTANCE");
identityOptions.ClientId = Configuration.GetValue("AZUREAD_CLIENTID");
identityOptions.TenantId = Configuration.GetValue("AZUREAD_TENANTID");
//identityOptions.AllowWebApiToBeAuthorizedByACL = true;
}
).EnableTokenAcquisitionToCallDownstreamApi(options =>
{
options.ClientId = Configuration.GetValue("AZUREAD_CLIENTID");
options.ClientSecret = Configuration.GetValue("AZUREAD_CLIENTSECRET");
options.TenantId = Configuration.GetValue("AZUREAD_TENANTID");
})
.AddInMemoryTokenCaches()
.AddMicrosoftGraph(opt =>
{
opt.Scopes = "User.Read GroupMember.Read.All";
});

The method that blows up is:
private async Task<IList> GetPermissionGroups(ClaimsPrincipal identity)
{

....... irrelevant code removed...

        //extracting just the id's for the list
        List<String> groupIds = entitlements.Select(x => x.AzureGuid).ToList();

//this line blows up when using 1.22.0 or 1.22.1
return await _graphServiceClient.Me.CheckMemberGroups(groupIds).Request().PostAsync();

    }

@luismanez
Copy link

Same issue here. In general, whatever that requires an ITokenAcquisition is not working fine. In my case, also downgrading to 1.21.1 fixes the issue. Can´t provide a public repo right now, but could do it soon if required, however, my setup is also quite "standard", following this sample: https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/master/4-WebApp-your-API/4-3-AnyOrg/ (using .net6 as @JRawlins737, but all works good with 1.21.1)

@luismanez
Copy link

Just adding a new finding.
When setting it up like:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
          .AddMicrosoftIdentityWebApi(builder.Configuration, "AzureAd")
            .EnableTokenAcquisitionToCallDownstreamApi()
               .AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
            .AddDistributedTokenCaches();

It works fine. However, in my scenario, I want to validate the Tenant in the token, so I´m doing:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
          .AddMicrosoftIdentityWebApi(options =>
              {
                  builder.Configuration.Bind("AzureAd", options);
                  options.Events = new JwtBearerEvents
                  {
                      OnTokenValidated = async context =>
                      {
                          string[] allowedTenants = {
                              "TENANT1_ID", 
                              "TENANT2_ID" 
                          };

                          string? tenantId = context.Principal?.Claims.FirstOrDefault(x => x.Type is "tid" or "http://schemas.microsoft.com/identity/claims/tenantid")?.Value;

                          if (!allowedTenants.Contains(tenantId))
                          {
                              throw new Exception("This tenant is not authorized");
                          }
                      }
                  };
              }, options => { builder.Configuration.Bind("AzureAd", options); })
            .EnableTokenAcquisitionToCallDownstreamApi(options =>
                {
                    builder.Configuration.Bind("AzureAd", options);
                })
               .AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
            .AddDistributedTokenCaches();

Previous setup fails with 1.22.1, but works with 1.21.1.

Note that the setup that works in 1.22.1, the AddMicrosoftIdentityWebApi is returning a MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration, but the failing setup, the AddMicrosoftIdentityWebApi is returning a MicrosoftIdentityWebApiAuthenticationBuilder

@jmprieur
Copy link
Collaborator

jmprieur commented Feb 2, 2022

@JRawlins737 @luismanez : do you want to try the version which is in master currently. We think we fixed it.
Otherwise we'd want to release it within a few days

@jmprieur jmprieur added bug Something isn't working and removed more info needed labels Feb 2, 2022
@JRawlins737
Copy link
Author

Works for me... :) thanks

@jmprieur
Copy link
Collaborator

jmprieur commented Feb 2, 2022

Thanks for confirming, @JRawlins737 !

@luismanez
Copy link

I´m having some issues manually adding the .dlls to my project, so will wait for the release. However, I´ve seen the library is not targeting .NET6. Is there any reason?

    <TargetFrameworks>netcoreapp3.1; net462; net472; net5.0</TargetFrameworks>

Thanks!

@jmprieur
Copy link
Collaborator

jmprieur commented Feb 2, 2022

The .NET 5.0 version works perfectly with .NET 6.0, @luismanez

@jennyf19
Copy link
Collaborator

jennyf19 commented Feb 2, 2022

fixed in 1.22.3 release

@jennyf19 jennyf19 closed this as completed Feb 2, 2022
@luismanez
Copy link

Works like a charm with 1.22.3 !!

Many thanks @jmprieur @jennyf19

@jennyf19 jennyf19 added this to the 1.22.3 milestone Feb 4, 2022
@jennyf19 jennyf19 modified the milestones: 1.24.0, 1.23 Apr 20, 2022
@vladkasianenko
Copy link

vladkasianenko commented Mar 29, 2024

Have the issue here as well.

Setup: Azure AD B2C
App registration:
image

Packages:

<PackageReference Include="Microsoft.Identity.Web" Version="2.17.4" />
<PackageReference Include="Microsoft.Identity.Web.MicrosoftGraph" Version="2.17.4" />

App Settings:

{
  "AzureAdB2C": {
    "Instance": "https://mytenant.b2clogin.com",
    "Domain": "mytenant.onmicrosoft.com",
    "TenantName": "mytenant",
    "TenantId": "guid",
    "ClientId": "guid",
    "ClientSecret": "qwerty123",
    "SignUpSignInPolicyId": "b2c_1_signup_signin",
    "MicrosoftGraph": {
      "BaseUrl": "https://graph.microsoft.com/v1.0",
      "Scopes": "https://graph.microsoft.com/.default User.ReadWrite.All"
    }
  }
}

Not working:

 services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddMicrosoftIdentityWebApi(async options =>
                    {
                        Configuration.Bind("AzureAdB2C", options);

                        var tenantName = Configuration.GetValue<string>("AzureAdB2C:TenantName");
                        var tenantId = Configuration.GetValue<string>("AzreAdB2C:TenantId");
                        var flowName = Configuration.GetValue<string>("AzureAdB2C:SignUpSignInPolicyId");
                        var audience = Configuration.GetValue<string>("AzureAdB2C:ClientId");

                        options.TokenValidationParameters = new TokenValidationParameters()
                        {
                          // Rest of the code
                        };

                        options.Events = new JwtBearerEvents()
                        {
                            OnTokenValidated = async context => {
                                // Rest of the code
                                await Task.CompletedTask;
                            }
                        };
                    }, options => { Configuration.Bind("AzureAdB2C", options); })
                     // This is not working
                    .EnableTokenAcquisitionToCallDownstreamApi(options => {
                        options.ClientId = Configuration["AzureAdB2C:ClientId"];
                        options.ClientSecret = Configuration["AzureAdB2C:ClientSecret"];
                        options.TenantId = Configuration["AzureAdB2C:TenantId"];
                    })
                    .AddMicrosoftGraph(Configuration["AzureAdB2C:MicrosoftGraph"])
                    .AddInMemoryTokenCaches();

But if I remove .EnableTokenAcquisitionToCallDownstreamApi(...), .AddMicrosoftGraph and .AddInMemoryTokenCaches(),
and register the service like this.
all is OK:

            services.AddHttpClient();
            services.AddScoped<GraphServiceClient>(serviceProvider =>
            {
                var scopes = new[] { "https://graph.microsoft.com/.default" };
                var clientId = Configuration["AzureAdB2C:ClientId"];
                var tenantId = Configuration["AzureAdB2C:TenantId"];
                var clientSecret = Configuration["AzureAdB2C:ClientSecret"];
                var options = new ClientSecretCredentialOptions
                {
                    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
                };

                var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
                return new GraphServiceClient(clientSecretCredential, scopes);
            });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working regression regression between Microsoft Identity Web versions
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants