无法使用IdentityServer4验证API中的JWT或access_token

问题描述 投票:0回答:1

我正在努力构建一些我们拥有现有系统的新功能。我们的目标是让不同的Angular SPA与API通信,为我们的遗留应用程序提供新的界面。团队已设置IdentityServer4以使用旧应用程序进行凭据验证。

用Angular 7编写的SPA使用隐式流进行身份验证。响应类型是“令牌id_token”我已经能够让这个流程工作,因为我可以让一个未经身份验证的用户访问该站点,被踢到IdentityServer身份验证屏幕,使用正确的凭据登录,然后重定向回到应用程序。当我获得令牌时,声明对象具有aud的单个值,SPA的client_id,例如spa-client。 access_token和id_token都是JWT,RS256作为签名方法。最后,我在SPA中创建了一个拦截器来发送JWT(实际上它只使用作为access_token发回的任何值)作为API请求上的“Bearer”令牌。

我现在已经创建了一个.NET Core 2.2 WebApi应用程序来构建SPA要使用的服务API。此应用程序使用IdentityServer4.AccessTokenValidation包来“保护”我已阅读IdentityServer4文档中的部分的API。在我的ConfigureServices方法中,我编写了以下内容来配置auth:

services    
    .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
    .AddIdentityServerAuthentication(options =>
    {
        if (string.IsNullOrWhiteSpace(serviceConfiguration.Authentication.Authority)) throw new ConfigurationException("", nameof(serviceConfiguration.Authentication.Authority), "An authority must be defined.");
        if (string.IsNullOrWhiteSpace(serviceConfiguration.Authentication.ApiName)) throw new ConfigurationException("", nameof(serviceConfiguration.Authentication.ApiName), "An api name must be defined.");

        options.Authority = serviceConfiguration.Authentication.Authority;
        options.ApiName = serviceConfiguration.Authentication.ApiName;

        if (!string.IsNullOrWhiteSpace(serviceConfiguration.Authentication.ApiSecret))
        {
            options.ApiSecret = serviceConfiguration.Authentication.ApiSecret;
        }

        options.RequireHttpsMetadata = false;
        options.SupportedTokens = SupportedTokens.Both;
    }

serviceConfiguration是我的JSON appsettings.json的强类型表示

我的理解是,options.SupportedTokens = SupportedTokens.Both将检查JWT并进行内省。

现在所有这些都是设置我已经采用了由API模板创建的简单示例ValuesController并添加了[Authorize]属性。在Postman中对此端点执行简单的GET请求会返回401,如我所料。

接下来我尝试登录SPA并转到测试页面,该测试页面将执行相同的操作,但拦截器将具有持有者令牌,access_token或基本上JWT。我仍然从服务中获得401。

查看服务输出的日志,我没有看到任何有用的具体内容:

info:Microsoft.AspNetCore.Hosting.Internal.WebHost [1]请求启动HTTP / 1.1选项http://localhost:5001/api/values信息:Microsoft.AspNetCore.Hosting.Internal.WebHost [1]请求启动HTTP / 1.1选项http://localhost:5001/api/values info:Microsoft.AspNetCore.Cors。 Infrastructure.CorsService [4] CORS策略执行成功。 info:Microsoft.AspNetCore.Cors.Infrastructure.CorsService [4] CORS策略执行成功。信息:Microsoft.AspNetCore.Hosting.Internal.WebHost [2]请求已完成61.1352ms 204信息:Microsoft.AspNetCore.Hosting.Internal.WebHost [2]请求已完成61.1272ms 204信息:Microsoft.AspNetCore.Hosting.Internal。 WebHost [1]请求启动HTTP / 1.1 GET http://localhost:5001/api/values应用程序/ json信息:Microsoft.AspNetCore.Hosting.Internal.WebHost [1]请求启动HTTP / 1.1 GET http://localhost:5001/api/values应用程序/ json信息:Microsoft.AspNetCore.Cors.Infrastructure.CorsService [ 4] CORS策略执行成功。 info:Microsoft.AspNetCore.Cors.Infrastructure.CorsService [4] CORS策略执行成功。 info:Microsoft.AspNetCore.Routing.EndpointMiddleware [0]执行端点'Examples.TestApp.API.Web.Controllers.ValuesController.Get(Examples.TestApp.API.Web)'info:Microsoft.AspNetCore.Routing.EndpointMiddleware [0]执行端点'Examples.TestApp.API.Web.Controllers.ValuesController.Get(Examples.TestApp.API.Web)'info:Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [1]路由与{action =“Get”匹配, controller =“Values”}。执行操作Examples.TestApp.API.Web.Controllers.ValuesController.Get(Examples.TestApp.API.Web)info:Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [1]与{action =“Get”匹配的路由,controller = “值”}。执行操作Examples.TestApp.API.Web.Controllers.ValuesController.Get(Examples.TestApp.API.Web)info:Microsoft.AspNetCore.Authorization.DefaultAuthorizationService [2]授权失败。 info:Microsoft.AspNetCore.Authorization.DefaultAuthorizationService [2]授权失败。 info:Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [3]过滤器'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'上的请求授权失败。 info:Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [3]过滤器'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'上的请求授权失败。 info:Microsoft.AspNetCore.Mvc.ChallengeResult [1]使用身份验证方案执行ChallengeResult()。 info:Microsoft.AspNetCore.Mvc.ChallengeResult [1]使用身份验证方案执行ChallengeResult()。 info:IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler [12] AuthenticationScheme:Bearer受到挑战。 info:IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler [12] AuthenticationScheme:Bearer受到挑战。 info:Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [2]在166.3038ms执行的例子.TestApp.API.Web.Controllers.ValuesController.Get(Examples.TestApp.API.Web)信息:Microsoft.AspNetCore.Mvc.Internal .ControllerActionInvoker [2]在162.8827ms中执行的例子.TestApp.API.Web.Controllers.ValuesController.Get(Examples.TestApp.API.Web)信息:Microsoft.AspNetCore.Routing.EndpointMiddleware [1]执行端点'Examples.TestApp .API.Web.Controllers.ValuesController.Get(Examples.TestApp.API.Web)'info:Microsoft.AspNetCore.Routing.EndpointMiddleware [1]执行端点'Examples.TestApp.API.Web.Controllers.ValuesController.Get(示例.TestApp.API.Web)'info:Microsoft.AspNetCore.Hosting.Internal.WebHost [2]请求在459.6677ms完成401信息:Microsoft.AspNetCore.Hosting.Internal.WebHost [2]请求在473.7648ms完成401

将日志记录设置为Trace并未显示任何其他内容。

我确实试图去Postman看看我是否可以手动对令牌进行内省。我设置了基本授权,并将用户名设置为“test-api”,api id和我在其客户端密钥中设置的密码。在正文中,将其设置为x-www-form-urlencoded,其密钥为“token”,值为access_token。我得到200 OK的声明和“active:true”。看起来应该是好的,对吗?

我不拥有IdentityServer实现,因此除了能够登录管理界面外,我不太确定该结果是什么。我已登录身份服务器的管理界面,并仔细检查了客户端和API的设置。客户端被授予“api”范围,API获得相同的范围“api”。这显示在内省响应中发回的范围以及我从客户端获得的令牌中。

我也试过设置options.SupportedTokens = SupportedTokens.Referenceoptions.SupportedTokens = SupportedTokens.JWT。没有任何改变。 :(

我究竟做错了什么?这是配置问题还是我是白痴(可能是后者)。

编辑:RE access_token和id_token

我原来的问题不正确。令牌是不同的(我需要看的不仅仅是标题部分)。

观众很奇怪。我在解码时从未注意过这里可能存在的差异。我的感知能力必须吸吮!

访问令牌有aud:“http:/// resources”id_token有aud:“spa-client”

c# authentication asp.net-core identityserver4 openid-connect
1个回答
2
投票

access_token和id_token都是相同的,是一个JWT,RS256作为签名方法。

access_token和id_token应该不一样。对于id_token,令牌中的audclaim应该是客户端的名称,但在访问令牌中,您的api名称应该包含在aud中,以便您的api资源可以验证发出访问令牌以进行“我的”api调用。您可以使用jwt.io等在线工具解码JWT令牌中的声明。由于您尚未发布客户端和IDS4的配置,因此应检查响应类型,范围......如果使用Fiddler跟踪请求,则应该:

GET /connect/authorize/callback?client_id=js&redirect_uri=http%3A%2F%2Flocalhost%3A5003%2Fcallback.html&response_type=id_token%20token&scope=openid%20profile%20api1&state=xxxxxxxxxxxxxxx&nonce=xxxxxxxxxxxxxxxxxxx

另外,来自文件:http://docs.identityserver.io/en/latest/topics/grant_types.html

对于基于JavaScript的应用程序,不再推荐使用Implicit。请使用PKCE使用授权码。

您可以单击here获取代码流代码示例。

更新:

访问令牌的受众还应包括api名称,除了"http:///resources

enter image description here

您可以单击here获取代码示例。

© www.soinside.com 2019 - 2024. All rights reserved.