【问题标题】:How to fix calling GetAccessTokenForAppAsync to acquire token resulting in a NullReferenceException?如何修复调用 GetAccessTokenForAppAsync 以获取导致 NullReferenceException 的令牌?
【发布时间】:2021-08-26 20:13:28
【问题描述】:

我正在研究如何在 ASP.NET Core 3.1 Razor Pages 应用程序中使用 Microsoft Graph API。我找到了this 指南,并得到了大部分工作(以及检索令牌),直到我意识到我需要在没有用户的情况下访问 API。

目前,我被卡住了,因为我无法使用 ITokenAcquisition GetAccessTokenForAppAsync 方法检索令牌。它不断导致NullReferenceException。我不知道我的启动设置是否错误或什么,但我无法弄清楚。

System.NullReferenceException: 'Object reference not set to an instance of an object.'

我知道Get access without a user 指南,我理解并且可以开始工作,但我特别想使用GetAccessTokenForAppAsync 方法,因为它会为我管理刷新令牌。否则,我必须在每次 API 调用中不断查询新令牌,并且不断生成有效令牌似乎是个坏主意。

Startup.cs ConfigureServices 方法:

public void ConfigureServices(IServiceCollection services)
{
    ...
    
    services.AddHttpClient();
    services.AddMicrosoftIdentityWebApiAuthentication(Configuration)
        .EnableTokenAcquisitionToCallDownstreamApi()
        // Use in-memory token cache
        // See https://github.com/AzureAD/microsoft-identity-web/wiki/token-cache-serialization
        .AddInMemoryTokenCaches();
        
    ...

}

索引.cshtml.cs。这是我打电话获取令牌的地方:

public class IndexModel : PageModel
{
    private readonly IHttpClientFactory _clientFactory;
    private readonly ITokenAcquisition _tokenAcquisition;

    public IndexModel(IHttpClientFactory clientFactory, ITokenAcquisition tokenAcquisition)
    {
        _clientFactory = clientFactory;
        _tokenAcquisition = tokenAcquisition;
    }

    public async Task OnGet()
    {
        // results in NullReferenceException
        string token = await _tokenAcquisition.GetAccessTokenForAppAsync("https://graph.microsoft.com/.default", tenant:"tenantId");
    }
}

appSettings.json。这些值由用户机密 json 填充。

{
  "AzureAd": {
    "Instance": "",
    "ClientId": "",
    "TenantId": "",
    "CallbackPath": "",
    "ClientSecret": "",
    "TimeoutInMinutes": ""
  },
  "ConnectionStrings": {
    "DefaultConnection": ""
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

【问题讨论】:

  • 您好兄弟,您尝试过更新的解决方案吗?如果还有什么可以帮助您的,请告诉我。

标签: c# asp.net-core microsoft-graph-api bearer-token


【解决方案1】:

首先我已经成功重现了您的问题,如下所示:

你得到这个是因为private readonly ITokenAcquisition _tokenAcquisition;

注意:这实际上是一项服务,可以帮助您代表应用程序获取访问令牌。您不能将此服务用作构造函数变量。

解决方案:

您应该按照以下方式使用ITokenAcquisition 服务:

   public async Task OnGet()
        {
            var _tokenAcquisition = this.HttpContext.RequestServices
                 .GetRequiredService<ITokenAcquisition>() as ITokenAcquisition;
            string token = await _tokenAcquisition.GetAccessTokenForAppAsync("https://graph.microsoft.com/.default", tenant: "tenantId");
        }

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();
}

DownstreamApi 在 appsettings.json 下:

"DownstreamApi": {
    "BaseUrl": "https://graph.microsoft.com/v1.0",
    "Scopes": "https://graph.microsoft.com/.default"
  }

输出:

希望它能相应地解决您的问题。

【讨论】:

  • 感谢您的回答。不幸的是,这对我不起作用。我仍然遇到同样的问题。也许您以不同的方式设置您的创业公司?或者,也许我在 Azure 中注册应用程序时遗漏了一些东西......
  • 请您分享您的 Startup.cs。此外,您是否从服务注册中禁用了 ITokenAquisition?
  • 感谢您的回复。您可以在原始帖子中看到我的 startup.cs 的相关部分。我应该禁用什么?是EnableTokenAcquisitionToCallDownstreamApi() 方法吗?
  • 不,兄弟,它的实现ITokenAcquisition 我怀疑这可能会导致此时出现问题public IndexModel(IHttpClientFactory clientFactory, ITokenAcquisition tokenAcquisition) { _clientFactory = clientFactory; _tokenAcquisition = tokenAcquisition; },因为你可以看到那个工作正是你正在寻找的。那么您能否用我的示例使用新控制器进行测试,以便您了解问题所在。如有任何进一步的问题,请随时分享。
  • 如果有帮助,我已经根据您当前的关注使用 startup.cs 配置文件更新了答案。试一试。
猜你喜欢
  • 1970-01-01
  • 2019-08-01
  • 2019-11-13
  • 1970-01-01
  • 2022-01-10
  • 2022-06-14
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
相关资源
最近更新 更多