'Null Reference Exception when calling GraphServiceClient from a .net core Razor application that uses OpenIdConnect

I am working on a DotNet Core Razor application that uses OpenIdConnect to authenticate against Azure AD. This site is currently targeting the .net 5.0 framework. I have the Openid connect authentication working for the site. My next goal is to use Microsoft Graph to query Azure AD for the groups that the user belongs to. I downloaded a quickstart and have successfully gotten that to run, also targeting the .net 5.0 framework. The quickstart site will execute the code I have written to get the groups that the user belongs to. When I configure my Razor site to run the same code, I get a null reference exception on the first attempt to use the GraphServiceClient object that is injected into the page. I have compared the Azure AD setup for the quickstart to the setup for the Razor site and cannot see any differences other than different values for ClientId and Client Secret.

Here is the section of code from the startup of the Razor site

string[] initialScopes = Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split('');
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration, "AzureAd", "AzureAD", cookieScheme: null, 
subscribeToOpenIdConnectMiddlewareDiagnosticsEvents: true)
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches(options => { options.AbsoluteExpirationRelativeToNow = 
TimeSpan.FromDays(90); });

which is identical to the code running in the quickstart site.

When I use the GraphServiceClient object injected into the page on the Razor site, with this call

currentUser = await _graphServiceClient.Me.Request().GetAsync();

I get a null reference error. Examining the GraphServiceClient object in the debugger does not reveal anything obvious, I have compared the object injected into the Razor site, which fails, against the object in the Quickstart site, which works, and don't have a clue as to any difference.

This is the Azure Ad section from the appsettings.json file.

"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "qualified.domain.name",
"TenantId": "<My Tenant Id>",
"ClientId": "<My client Id>",
"CallbackPath": "/signin-oidc",
"ClientSecret": "<My client secret>",
"ClientCertificates": [],
// the following is required to handle Continuous Access Evaluation challenges
"ClientCapabilities": [ "cp1" ]
},
"DownstreamApi": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "User.Read"
},

Here are the settings for API permissions in Azure AD

I can post the stack trace of the error and any other relevant information.

This is the link to the quickstart that I have working:

Here are the details of the exception that happens on the call to the GraphServiceClient object.

Inner exception

IDW10503: Cannot determine the cloud Instance. The provided authentication scheme was ''. Microsoft.Identity.Web inferred 'Identity.Application' as the authentication scheme. Available authentication schemes are 'AzureAD,Identity.Application,Identity.External,Identity.TwoFactorRememberMe,Identity.TwoFactorUserId'.

Stack Trace:

at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.HttpProvider.<SendAsync>d__18.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.BaseRequest.<SendRequestAsync>d__40.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.BaseRequest.<SendAsync>d__34`1.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Graph.UserRequest.<GetAsync>d__5.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at AdminPanel.Areas.Identity.Pages.Account.ExternalLoginModel.<GetSecurityGroups>d__29.MoveNext() 



Solution 1:[1]

I have the same error with a Teams App using Graph authentication code that works perfectly well in a Blazor Server app.

My Blazor startup code looks like this:

    builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
.AddDownstreamWebApi("DownstreamApi",builder.Configuration.GetSection("DownstreamApi"))
     .AddInMemoryTokenCaches();

Graph JSON is:

 "MicrosoftGraph": {
    "Scopes": "user.read",
    "BaseUrl": "https://graph.microsoft.com/v1.0"
  },

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1