资源服务器 API 上的 OpenIddict MVC 核心 2.0 和 JWT

Posted

技术标签:

【中文标题】资源服务器 API 上的 OpenIddict MVC 核心 2.0 和 JWT【英文标题】:OpenIddict MVC core 2.0 and JWT on resource server API 【发布时间】:2018-03-07 10:42:16 【问题描述】:

我一直在设置一个 OpenIdDict 身份验证服务器,以便与我们现有的 mvc core 2.0 Web 应用程序一起使用。在我们的生产应用程序上实现 OpenIdConnect 部分之前,我正在使用代码流并制作了一个测试 mvc webapp 资源服务器。

一切似乎都按预期工作,我可以登录并访问我的资源。

我需要在新的身份验证架构下为我的其余客户端获取 api 承载身份验证。 Api 放在同一个资源服务器上。

我已经使用以下方法为 JWT 设置了 OpenIddict:

            options.AllowPasswordFlow();
            options.UseJsonWebTokens();
            options.AddSigningKey(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetSection("TokenAuthentication:SecretKey").Value)));

...添加了 JwtBearer

        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();

        services.AddAuthentication()
            .AddJwtBearer(options =>
            
                options.Authority = "http://localhost:17004/";
                options.Audience = "MyAudience";
                options.RequireHttpsMetadata = false;
                options.TokenValidationParameters = new TokenValidationParameters
                
                    NameClaimType = OpenIdConnectConstants.Claims.Subject,
                    RoleClaimType = OpenIdConnectConstants.Claims.Role,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetSection("TokenAuthentication:SecretKey").Value))
                ;
            );

...并在 AuthorizationController.Exchange 中添加了用于处理密码流令牌请求的代码。

在我的资源服务器 Startup.cs 上,我添加了 AddOpenIdConnect 并添加了signingKey(与我的身份验证服务器上的密钥相同)。

            options.ResponseType = OpenIdConnectResponseType.Code;
            options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;
            options.TokenValidationParameters = new TokenValidationParameters()
            
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetSection("TokenAuthentication:SecretKey").Value))
            ;
            options.Authority = "http://localhost:17004/";

设置完成后,我的资源服务器仍然可以进行身份​​验证,一切正常,我可以使用 restclient 从我的身份验证服务器获取 jwt 令牌,但是当尝试访问资源服务器上的我的 api 时,它失败了,因为没有验证器承载方案。

如果我在资源服务器上使用 TokenValidationParameters 中的相同签名密钥添加调用 AddBearerToken ,它实际上可以工作。挑战成功,我可以访问我的资源。

但是我怀疑我的设置远非正确,因为我可以看到,在调用我的 api 时,我的令牌验证正在资源服务器上进行,所以我有 2 个问题。

    是否可以让 JwtBearer 中间件将验证转发到我的身份验证服务器? (openidConnect 可以处理吗?)

    是否可以让我的资源服务器转发/passthru 令牌发出请求也是我的身份验证服务器,这样我的 rest api 客户端就不必处理 2 个服务器?

【问题讨论】:

【参考方案1】:

是否可以让 JwtBearer 中间件将验证转发到我的身份验证服务器? (openidConnect 可以处理吗?)

JWT 不记名中间件始终使用从 OpenIddict 的配置端点检索到的签名密钥执行本地验证。您无法强制它将此任务委托给 OpenIddict。

是否可以让我的资源服务器转发/通过令牌发出请求也是我的身份验证服务器,这样我的其余 api 客户端就不必处理 2 个服务器?

如果您想将令牌验证部分委托给您的授权服务器,请不要使用 JWT 中间件。相反,在 OpenIddict 选项中启用自省,创建一个新的机密客户端应用程序注册并使用 aspnet-contrib introspection middleware,这将使用反向通道 HTTP 调用来验证传入的令牌。

【讨论】:

在我向 OpenIddict 身份验证服务器添加证书后,jwks 工作并且资源服务器端可以从中获取密钥,我知道验证将在资源服务器上进行,这很好(这是多次注册令我担心的签名密钥)。但是我的 REST 客户端应用程序仍然需要直接联系身份验证服务器以进行初始令牌发行。我可以通过我的资源服务器做到这一点吗? ...您还提到,就我而言,我不应该在资源服务器上使用 OpenIdConnect。您能否提供一个如何仅使用 JwtBearer 设置资源服务器的示例? (删除 openidconnect 后,auth.controller 中的挑战失败,因为 openidconnect 方案不存在处理程序。如果我将方案更改为“Bearer”,它永远不会联系身份验证服务器,只给出 401。) 我最终在我的资源服务器上创建了一个小型发现方法,告诉我的 REST 客户端在哪里找到权限,然后在身份验证服务器上使用 .well-known/openid-configuration 来查找令牌端点。【参考方案2】:

JWT 是一种令牌格式,是 OpenIdConnect 所必需的。您可以在 Oauth2 中使用任何令牌格式,包括 JWT。所以你不需要跳过 JWT。

【讨论】:

我认为我在理解一些基础知识方面存在问题,因为您写的文字对我来说毫无意义。我花了很多时间试图弄清楚哪个流程的一部分以及在哪里使用了哪些技术,而在找出如何为其配置 mvc core 2.0 以及应该如何实现 oid 工作之间,我完全迷失了。 我写了一篇关于这个的文章,它概述了这些概念。链接在这里 - linkedin.com/pulse/… 好文章。我还发现了有关我的 mvc 设置的更多信息并编辑了我的问题,因为我现在可以提出正确的问题了。

以上是关于资源服务器 API 上的 OpenIddict MVC 核心 2.0 和 JWT的主要内容,如果未能解决你的问题,请参考以下文章

OpenIddict:如何在资源服务器中注册签名密钥以验证令牌?

OpenIddict 的临时关键问题

将 OpenIddict 作为容器运行时令牌颁发者的问题

OpenIddict:当两个或更多服务实例计数时出现 401 错误

OpenIddict 缺少强制性的“code_challenge”参数

OpenIddict 支持通过 GET 请求返回授权码给邮递员