【问题标题】:Use both OpenIdConnect and JWT Bearer Token with Microsoft Identity Web ASP.NET Core 3.1将 OpenIdConnect 和 JWT 不记名令牌与 Microsoft Identity Web ASP.NET Core 3.1 一起使用
【发布时间】:2020-08-31 12:01:39
【问题描述】:

我想让某人使用 OpenIdConnect 或使用持有者令牌的 OAuth 2.0 授权代码流在浏览器中访问我的 API。这是我在 Microsoft D365 OData 端点中看到的类似功能。我可以通过浏览器访问它们,但它们需要用户身份验证,或者我可以通过带有不记名令牌的 HTTP GET 访问它们。

如果我这样配置 Web API:

services.AddProtectedWebApi(this.Configuration).
AddSignIn(this.Configuration);

我可以从浏览器访问 GET API,如果我尚未通过身份验证,它会提示我输入凭据并进行身份验证。但是,如果我尝试使用不记名令牌从 Postman 访问相同的 API,它会返回一个网页进行身份验证。

如果我这样配置 Web API:

services.AddProtectedWebApi(this.Configuration);

我在浏览器中收到 401 错误,但我可以使用不记名令牌从 Postman 访问 API。

如果提供了不记名令牌,我希望能够使用它,否则会挑战用户凭据。

我的控制器用户[Authorize] 我目前没有在 GET 操作中使用任何验证。我让中间件做所有的验证。

【问题讨论】:

    标签: web-applications asp.net-identity asp.net-core-webapi


    【解决方案1】:

    我通过将方案添加到控制器上的[Authorize] 属性解决了这个问题。我将属性更改为[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme + "," + JwtBearerDefaults.AuthenticationScheme)],这将允许我在浏览器中进行身份验证(通过登录 D365 或办公室),然后将对我进行 API 身份验证。如果我使用不记名令牌从 Postman 调用 API,它也会成功验证。

    我确实看到了一种奇怪的行为。如果我尚未在浏览器中进行身份验证(或者如果我启动了隐身会话),则不再提示我输入我的凭据,并且我会收到 401 结果。但是,如果我用[Authorize][Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme] 装饰控制器,我将在浏览器中提示并成功通过身份验证,但 Postman 将收到登录页面,而不是通过不记名令牌进行身份验证。

    我还注意到IAuthenticationSchemeProvider.GetRequestHandlerSchemesAsync() 总是返回OpenIdConnectDefaults.AuthenticationScheme 作为请求方案。奇怪的是,来自 Postman 的使用 JwtBearerDefaults.AuthenticationScheme 的调用仍然返回 OpenIdConnectDefaults.AuthenticationScheme 作为请求方案。

    我希望这对其他人有帮助。

    【讨论】:

      【解决方案2】:

      过去一周我一直在调查这个完全相同的问题,并且遇到了您在更新帖子中描述的相同 401 问题。我想我今天可能遇到了突破。

      https://github.com/aspnet/Security/issues/1469#issuecomment-399239254的启发,我想出了以下内容:

      Startup.cs

      services.AddProtectedWebApi(
          options =>
          {
              Configuration.Bind("AzureAd", options);
              options.ForwardDefaultSelector = (context =>
              {
                  var authHeader = context.Request.Headers["Authorization"].ToArray();
                  if (authHeader.Length > 0 && authHeader[0].StartsWith("Bearer "))
                  {
                      return JwtBearerDefaults.AuthenticationScheme;
                  }
      
                  return OpenIdConnectDefaults.AuthenticationScheme;
              });
          },
          configureMicrosoftIdentityOptions: options => Configuration.Bind("AzureAd", options),
          tokenDecryptionCertificate: certificate
      );
      
      services.AddSignIn(Configuration);
      

      然后对于我的控制器,我用[Authorize] 属性装饰它们,并通过我实现的实现IControllerModelConvention 的类设置OpenIDConnect 和JwtBearer 身份验证方案,灵感来自https://joonasw.net/view/apply-authz-by-default,但应用计划而不是政策(因为这不起作用)。

      【讨论】:

        猜你喜欢
        • 2020-10-19
        • 2016-11-20
        • 2019-08-30
        • 2016-09-25
        • 2016-03-06
        • 2020-07-09
        • 2022-11-26
        • 2016-12-17
        • 2020-05-14
        相关资源
        最近更新 更多