我正在研究如何在 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 guide 我理解并且可以开始工作,但我特别想使用
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();
...
}
Index.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");
}
}
应用程序设置.json。这些值由用户机密 json 填充。
{
"AzureAd": {
"Instance": "",
"ClientId": "",
"TenantId": "",
"CallbackPath": "",
"ClientSecret": "",
"TimeoutInMinutes": ""
},
"ConnectionStrings": {
"DefaultConnection": ""
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
首先我已经成功重现了你的问题,如下所示:
你得到这个是因为
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"
}
输出:
注意: 确保您已在 program.cs 或 startup.cs 文件中包含
app.UseAuthentication();
。
希望它能相应地解决您的问题。