【问题标题】:How Jwt token issued by IdentiyServer is validate in Web Api ApplicationIdentiyServer 发布的 Jwt 令牌如何在 Web Api 应用程序中验证
【发布时间】:2021-06-04 19:24:30
【问题描述】:

我正在使用 IdentiyServer 向客户端发出 JWT 令牌,令牌包含角色声明和其他一些声明,这部分工作正常,我获得了具有所需声明的访问令牌。

在我的 Web API 应用程序中,我添加了以下代码来支持 JWT 身份验证:

 services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = false;
                options.Authority = "http://localhost:5004";
                IdentityModelEventSource.ShowPII = true;
                options.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateAudience = false,
                    ValidateIssuer = false,
                    ValidateLifetime = false,
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = "what is this ?"
                };

问题是,假设黑客生成带有任何标头和正文的 JWT 令牌并声称他想要并对其进行签名,我的 Web api 应用程序如何验证签名?如何与 identityServer 和我的 Web api 应用程序共享 IssuerSigningKey?

IssuerSigningKey和identityServer中的ClientSecrets一样吗?

我浏览了 IdentityServer 文档,但找不到答案。

【问题讨论】:

  • 这个要明确区分,身份服务器生成访问令牌用于认证,而jwt令牌将由应用程序生成,使用对称/非对称加密进行签名。 Google OAuth 不会生成 JWT,类似地,开放 id 服务器将生成访问令牌而不是授权令牌,即 JWT
  • 请检查我编辑的回复,我尝试在其中添加代码,这将有助于asp.net web api C#,尽管我的工作主要是在python fast api中

标签: c# jwt identityserver4 webapi bearer-token


【解决方案1】:

虽然黑客当然可以生成带有一些标头和声明的虚假 JWT,但他无法使用服务器的私钥签署令牌,除非他还入侵了您的服务器以窃取密钥。因此,在实践中,JWT 通常在令牌末尾带有 checksum,这是基于令牌内容和服务器密钥的哈希。如果您的服务器收到传入的 JWT 并且校验和未验证,那么它应该拒绝该 JWT。

【讨论】:

  • 如何在 web api 上验证签名?我应该使用公钥来验证签名吗?
  • 我不太了解您的 API 或 .NET,无法回答您的评论。但是校验和是你需要检查的。
【解决方案2】:

当您使用 AddJwtBearer 时,它会从您的 IdentityServer (http://localhost:5004) 下载公共签名密钥,并使用此公共密钥来验证收到的 JWT 令牌中的签名是否由预期的颁发者颁发。 AddJwtBearer 默认每 24 小时刷新一次下载的公钥。

IssuerSigningKey 不需要在 API 中设置。一般来说,您应该在 TokenValidationParameters 对象中禁用尽可能少的检查。

在生产中,您应该尝试将 ShowPII 设置为 false,否则令牌和其他机密之类的内容可能最终会出现在日志中。

IssuerSigningKey 和 IdentityServer 中的 ClientSecrets 一样吗?

不,它们是两个不同的东西。 ClientSecret 在针对 IdentityServer 进行身份验证时就像客户端的密码。

您在 IdentityServer 中设置的SigningKey,它代表公钥/私钥签名密钥。密钥可以是 RSA 或 ECDSA 密钥。

【讨论】:

    【解决方案3】:

    在问题看来,使用 OAuth 或 Open Id 服务器的完整 OAuth 流程不是很清楚,让我们考虑各种问题和选项。

    我正在使用 IdentiyServer 向客户端发出 JWT 令牌,令牌包含角色声明和其他一些声明,这部分工作正常,我获得了具有所需声明的访问令牌。

    让我们将身份验证服务器与授权分离,通常当我们集成任何社交登录时,它们所做的是提供访问令牌,我们使用回调在我们的服务器上生成 JWT 授权令牌,我们像后端服务器一样控制它

    两者有什么区别?

    身份验证服务器通常对我们了解的很少,大多只是验证电子邮件并返回成功,他们无法分配角色和其他详细信息,这些信息因应用程序而异

    那我们该怎么办?

    接收访问令牌,从中获取电子邮件等详细信息,获取与该电子邮件相关的所有详细信息,创建 json 有效负载,使用具有对称(仅一个密钥)或非对称加密(生成私钥公钥对)的算法,检查this video 更清楚地了解有关 JWT 的详细信息。在对称加密中,我们使用相同的密钥进行编码/解码,而在非对称加密中,我们使用私钥进行编码并使用公钥进行解码。正如您所检查的那样,在 JWT 中编码和解码只是意味着散列 header.payload 并比较两者以确保没有篡改

    关于加密类型和黑客的剩余问题:

    1. 非对称加密更强大、更安全,但会降低性能
    2. 如果客户端 Ui (Javascript) 不需要解码 JWT,那么对称加密就足够了
    3. 在非对称加密中,每个客户端都有一个公钥,而主令牌使用私钥签名,如果令牌被更改/篡改,则解码密钥将失败,从而出错。匹配键只是比较header.jsonpayload的哈希值
    4. 在对称加密中,保留在服务器上的 onky 1 密钥用于解码客户端传递的 jwt 令牌。
    5. 通过网络嗅出 JWT 令牌的黑客,别无选择,只能使用相同的令牌,否则令牌解码将失败,因此最好的选择是模拟,但这也很好,直到时间到期,这就是为什么有一个刷新令牌,无缝刷新访问令牌和插入的应用程序将生成新的 jwt 令牌。现在也有针对假冒的检查,为什么在尝试从未知机器登录时弹出消息
    6. 为什么在每次调用中,我们都不去身份服务器,因为那会使令牌验证过程变慢,这也是生成 JWT 的原因
    7. 对 web api 的每次调用都应使用插入的中间件来解码/验证令牌并继续进行,仅当 JWT 令牌过期时才会发生重新登录/身份验证

    ASP.Net Web API 特定更改

    我在 Python 中使用 Fast API 进行编码,我们所做的是使用 middleware,它类似于 Asp.Net 中的拦截器/过滤器,它将拦截对控制器/api 的所有调用,获取令牌,解码,验证并允许调用继续或抛出错误重新登录,请注意编码发生在来自身份验证服务器的callback 中。 Python 中的示例代码,https://pyjwt.readthedocs.io/en/latest/usage.html

    对于 C#,此链接是一个不错的选择,https://www.c-sharpcorner.com/article/asp-net-web-api-2-creating-and-validating-jwt-json-web-token/

    您可以在此处看到代码,其中添加了显式过滤器以验证令牌。它使用装饰器[Authorize] 来调用授权过滤器

    public static void Register(HttpConfiguration config) {  
     // Web API configuration and services    
     config.SuppressDefaultHostAuthentication();  
     config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));  
      
     // Web API routes    
     config.MapHttpAttributeRoutes();  
      
     config.Routes.MapHttpRoute(  
      name: "DefaultApi",  
      routeTemplate: "api/{controller}/{action}/{id}",  
      defaults: new {  
       id = RouteParameter.Optional  
      }  
     );  
    }  
    

    【讨论】:

      猜你喜欢
      • 2019-01-27
      • 2021-11-16
      • 2018-06-29
      • 1970-01-01
      • 2021-12-16
      • 2023-02-24
      • 2021-12-09
      • 2019-05-01
      • 1970-01-01
      相关资源
      最近更新 更多