【问题标题】:Microsoft Graph API authorization error: Invalid AudienceMicrosoft Graph API 授权错误:无效的受众
【发布时间】:2020-04-29 21:32:23
【问题描述】:

我知道这是一个很长的问题,但如果有人能与我分享他们的想法或经验,我将不胜感激,因为我已经在这方面工作了几天,现在正在尝试很多事情。我有一个 ASP Net Core 3.1 Web API 应用程序和一个 ASP.NET Core 3.1 MVC 应用程序。

两者都已在 Azure AD 中注册。 API 项目应该根据从 MVC 项目接收到的请求负载创建日历事件。我正在遵循来自this link here 的 Microsoft 指示

但是一旦 API 项目对 Microsoft Graph 进行调用,它就会失败并出现以下错误:

"code": "InvalidAuthenticationToken",
"message": "访问令牌验证失败。无效的受众。",

我在这里尽量提供更多信息,但整个示例可以从the link above 下载。

ASP.NET Core MVC Startup.cs:

services.AddAuthentication(sharedOptions =>
        {
            sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
       .AddAzureAd(options =>
       {
           Configuration.Bind("AzureAd", options);
           AzureAdOptions.Settings = options;
       })
       .AddCookie();

ASP.NET Core MVC 项目AddAzureAd 函数:

public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action<AzureAdOptions> configureOptions)
{
    builder.Services.Configure(configureOptions);
    builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, ConfigureAzureOptions>();
    builder.AddOpenIdConnect();
    return builder;
}

ConfigureAzureOptions:

public void Configure(string name, OpenIdConnectOptions options)
{
    options.ClientId = _azureOptions.ClientId;
    options.Authority = _azureOptions.Authority;
    options.UseTokenLifetime = true;
    options.CallbackPath = _azureOptions.CallbackPath;
    options.RequireHttpsMetadata = false;
    options.ClientSecret = _azureOptions.ClientSecret;
    options.Resource = "https://graph.microsoft.com"; // AAD graph

    // Without overriding the response type (which by default is id_token), the OnAuthorizationCodeReceived event is not called.
    // but instead OnTokenValidated event is called. Here we request both so that OnTokenValidated is called first which 
    // ensures that context.Principal has a non-null value when OnAuthorizeationCodeReceived is called
    options.ResponseType = "id_token code";

    // Subscribing to the OIDC events
    options.Events.OnAuthorizationCodeReceived = OnAuthorizationCodeReceived;
    options.Events.OnAuthenticationFailed = OnAuthenticationFailed;
}

以下是 API 项目中用于配置 Azure 选项的代码:

private class ConfigureAzureOptions : IConfigureNamedOptions<JwtBearerOptions>
{
    private readonly AzureAdOptions _azureOptions;

    public ConfigureAzureOptions(IOptions<AzureAdOptions> azureOptions)
    {
        _azureOptions = azureOptions.Value;
    }

    public void Configure(string name, JwtBearerOptions options)
    {
        // options.Audience = _azureOptions.ClientId;
        options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}";

        // The valid audiences are both the Client ID(options.Audience) and api://{ClientID}
        // --->>> I've changed this to also have "https://graph.micrososft.com" but no luck
        options.TokenValidationParameters.ValidAudiences = new string[] { _azureOptions.ClientId, $"api://{_azureOptions.ClientId}" }; // <<--- I've changed this to "https://graph.micrososft.com" but no luck

        // If you want to debug, or just understand the JwtBearer events, uncomment the following line of code
        // options.Events = JwtBearerMiddlewareDiagnostics.Subscribe(options.Events);
    }

    public void Configure(JwtBearerOptions options)
    {
        Configure(Options.DefaultName, options);
    }
}

这就是我从 MVC 项目获得令牌的方式 - 权限是 api://client_id:

string userObjectID = User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value;
            //AuthenticationContext authContext = new AuthenticationContext(AzureAdOptions.Settings.Authority, new NaiveSessionCache(userObjectID, HttpContext.Session));
            AuthenticationContext authContext = new AuthenticationContext(AzureAdOptions.Settings.Authority);
            ClientCredential credential = new ClientCredential(AzureAdOptions.Settings.ClientId, AzureAdOptions.Settings.ClientSecret);

感谢您对此的想法和经验 - 再次感谢您的宝贵时间。

【问题讨论】:

标签: c# asp.net azure oauth-2.0 microsoft-graph-api


【解决方案1】:

您的客户端应用似乎正在获取 Microsoft Graph API 令牌:

options.Resource = "https://graph.microsoft.com"; 

访问令牌的受众(aud 声明)指定了它的用途。 您的客户端应用程序需要使用 API 的客户端 ID 或应用程序 ID URI 作为资源。 通过这种方式,您可以获得适用于您的 API 的访问令牌。

那里的资源选项仅限于一个 API。 如果您需要多个 API 的令牌, 您需要为 AuthorizationCodeReceived 设置事件侦听器并使用 MSAL.NET 交换令牌的授权代码。 我有一个执行此操作的示例应用程序:https://github.com/juunas11/aspnetcore2aadauth/blob/97ef0d62297995c350f40515938f7976ab7a9de2/Core2AadAuth/Startup.cs#L58。 虽然此应用使用 .NET Core 2.2 和 ADAL,但使用 MSAL 的一般方法类似。

【讨论】:

  • 我已经尝试过了,但还没有工作,但我会赞成你的答案,因为我从你的代码中学到了很多好东西。谢谢。为了更加清晰,我还添加了获取令牌的代码。谢谢。
猜你喜欢
  • 2021-12-28
  • 1970-01-01
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多