3

我正在尝试使用来自 azure 活动目录的访问令牌来构建一个新的 WebApi。

我正在使用 .net core v3.1 和 Visual Studio 2019。

我使用“Asp.net 核心 Web 应用程序”模板创建了一个新项目并选择了一个“API”项目并将身份验证类型更改为“工作或学校帐户”并将 App ID Url 设置为 Api://Automation/TestApi

然后,Visual Studio 为我搭建了一个带有模拟天气预报服务的 Web API,如果我注释掉 [Authorize] 属性,它会按预期在浏览器中很好地启动。它还在 AzureActive Directory 中为我创建了一个应用程序注册。

恢复 [Authorize] 属性后,我无法从客户端应用程序调用 API,因此我决定使用邮递员调用 API 以查看发生了什么。

我向创建的应用程序注册视觉工作室添加了一个客户端密码,并使用应用程序(客户端)ID 和 api://Automation/TestApi/.default 作为范围将邮递员请求放在一起,如下所示。

邮递员调用令牌端点

这工作正常并返回访问令牌但是当我尝试使用该访问令牌来调用默认的天气预报端点时,我在 WWW-Authenticate 响应标头中收到 HTTP 401 未经授权的错误

"Bearer error="invalid_token", error_description="受众 'api://Automation/TestApi' 无效"

有什么我想念的吗?我找不到任何关于观众应该是什么的线索,也没有明显的控制方法。

As Requested here 是公开 API 屏幕的内容

公开一个 API

和我正在使用的解码的 jwt 令牌

在此处输入图像描述

更新

我在下面尝试了@CarlZhao 的答案,但它并没有真正起作用。但是我记得我刚才问过一个关于令牌中错误发行者的问题,结果是手动编辑 API 注册中的清单 json 并设置“accessTokenAcceptedVersion”:2

现在我得到了一个以 clientId guid 作为观众的 v2 函数

V2智威汤逊

但是,使用此令牌仍然不起作用!我现在收到有关发行者的错误:

Bearer error="invalid_token", error_description="The issuer 'https://login.microsoftonline.com/{{guid}}/v2.0' is invalid

4

3 回答 3

1

您错过了一些重要步骤,您的访问令牌也是错误的,它缺少必要的权限。你可以尝试按照我的方法:

您需要创建2个应用程序,一个代表客户端应用程序,另一个代表api应用程序,然后使用客户端应用程序调用Web api应用程序。

首先需要暴露代表web api的应用程序的api,可以按照如下流程进行配置:

Azure 门户>应用注册>公开 API>添加范围>添加客户端应用程序

因为你使用的是客户端凭证流,接下来需要定义api应用的manifest,并给你的客户端应用授予应用权限(这个是你自己定义的角色权限,添加权限的时候可以在我的API中找到) .然后您需要单击管理员同意按钮以授予管理员对此权限的同意。

是定义清单的过程。

在此处输入图像描述

这是为客户端应用程序授予权限:

在此处输入图像描述

最后,您可以为您的 api 应用程序请求一个令牌:

在此处输入图像描述

解析令牌,您将看到:

在此处输入图像描述

于 2020-10-30T10:26:19.470 回答
0

我找到了一种更好的方法,所以我想我会发布答案作为我第一个答案的替代方案。

我发现了这个非常好的示例应用程序和教程,并完成了第一部分“桌面应用程序调用 Web Api”,并生成了一个使用正确端点的 api,并以更可预测的方式处理验证令牌。如果您要说明一个新的 Web API,我建议使用它作为起点,而不是 Visual Studio 搭建的 api。

获取脚手架天气预报 api 以接受令牌访问令牌

  • 您需要为客户端和 api 以及@Carl Zhao 建议的范围和上面链接的教程分别注册应用程序。
  • 将 Microsoft.AspNetCore.Authentication.AzureAD.UI nuget 包替换为 Microsoft.Identity.Web
  • 在配置服务中的 startup.cs 中,将对 services.AddAuthentication(...).AddAzureAdBearer(...) 的调用替换为对 AddMicrosoftIdentityWebApiAuthentication 的调用
  • 删除 Microsoft.AspNetCore.Authentication.* 的 using 指令并使用 Microsoft.Identity.Web 添加;

这是我的配置服务现在的样子

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMicrosoftIdentityWebApiAuthentication(Configuration);

        services.AddControllers();
    }

我的其他答案中提供的自定义颁发者验证器不是必需的,可以删除。

于 2020-11-04T22:27:15.920 回答
0

我已经取得了一些进一步的进展,我将用它来提供我自己的答案。

生成的代码使用 Microsoft.AspNetCore.Authentication.AzureAD.UI 包 v 3.1.x 来验证令牌。

使用 Fiddler 我能够看到它使用的是旧端点而不是当前的“V2.0”端点。

这样做的意义在于,代币版本决定了代币中返回的受众和发行者。

在 V1 令牌中,受众是来自应用程序注册的“Application Id Url”,发行者是“https://sts.windows.net/{tennantId}”

在 v2 令牌中,受众是应用程序注册的客户端 ID (GUID),颁发者是https://login.microsoftonline.com/{tenantId}/V2.0

根本问题是这个库期望某种混合令牌具有 v2.0 令牌的受众价值(例如客户端 ID),但来自 v1 发行者https://sts.windows.net/

我找不到让它查看 v2.0 端点进行配置的方法,但我在 git hub 上发现了许多旧问题,这些问题已经关闭而没有解决。

尤其是

我的解决方法是在应用程序注册的应用程序注册“清单”json 中设置“accessTokenAcceptedVersion”:2。这确保了正确的受众在令牌中。

第二步,在启动类的 ConfigureServices 方法中添加自定义颁发者验证。这是我的代码

  AzureADOptions opt = new AzureADOptions();
  Configuration.Bind("AzureAd", opt);
  string expectedIssuer = $"{opt.Instance}{opt.TenantId}/v2.0";
  services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
        {
            options.TokenValidationParameters.IssuerValidator = (issuer, securityToken, validationParameters) =>
            {
                if (issuer == expectedIssuer) return issuer;

                throw new SecurityTokenInvalidIssuerException("Invalid Issuer")
                {
                    InvalidIssuer = issuer
                };
            };
        });

这确实感觉就像我正在扫除地毯下的错误和/或错误配置的中间件的潜在问题,我不禁想到一定有更简单的东西 - 毕竟这是从 Visual Studio 2019 向导生成的启动代码。

于 2020-11-02T17:51:48.997 回答