【问题标题】:ASP.NET Core: How to validate a JWT without access to the internetASP.NET Core:如何在不访问 Internet 的情况下验证 JWT
【发布时间】:2020-05-18 13:19:58
【问题描述】:

这就是我在后端验证 JWT 不记名令牌的方式:

services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.Authority = $"https://{Configuration["Auth0:Authority"]}";
                options.Audience = Configuration["Auth0:Audience"];
            });

它工作正常,因为 .Net 核心与权威机构协商以获取所需的信息(例如签名密钥)。在我的情况下,它通过 https://.auth0.com/.well-known/openid-configuration 与 Auth0 服务器通信。

问题是当我将应用程序部署在无法访问 Internet 的 Intranet 中时,我的应用程序无法与 Auth0 服务器通信。这是我得到的错误:

System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://< My TENANT >.auth0.com/.well-known/openid-configuration'.

我尝试手动输入 RSA 密钥,但运气不佳,同样的错误:

AddJwtBearer(options =>
            {
                options.Authority = $"https://{Configuration["Auth0:Domain"]}";
                options.Audience = Configuration["Auth0:Audience"];
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateLifetime = true,
                    RequireSignedTokens = true,
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = GetRsaKey(),
                };
            }); 

 private SecurityKey GetRsaKey()
        {
            byte[] modulus = Decode("r5cpJ....-fUGjJCH1QQ");
            byte[] exponent = Decode("A...AB");

            var rsaParameters = new RSAParameters
            {
                Modulus = modulus,
                Exponent = exponent
            };

            using var rsaProvider = new RSACryptoServiceProvider();
            rsaProvider.ImportParameters(rsaParameters);
            return new RsaSecurityKey(rsaProvider);
        }

有什么解决方法吗?

【问题讨论】:

  • 使用 keycloak 开源 SSO 作为 JWT Token 验证器。简单又安全

标签: asp.net-core jwt openid-connect


【解决方案1】:

TokenValidationParameters 可用于您想要验证令牌而不访问发行服务器的情况。然后你不能设置 Authority ,设置 ValidateIssuerSigningKeyValidateIssuer ,最后设置 IssuerSigningKey 这是用于验证传入 JWT 令牌的公钥。 Herehere 是代码示例。

但问题是因为您无法与 Auth0 交谈,这意味着您无法获得最新的公钥来验证 Auth0 颁发的令牌,您应该确认您的本地公钥与最新的公钥同步通过 Auth0 。如果身份验证也由您控制,您可以考虑使用Identity Server4,这是一个本地身份验证/SSO 框架,或者您可以实现 JWT 身份验证,如here 所示。

【讨论】:

    【解决方案2】:

    既然您是do not have access to the internet,您就需要像Identity Server 一样拥有本地身份和访问控制,或者创建您自己的JWT Issuer/Validator,如下所示:

    1. 获取私钥。
    2. 每当用户登录时,都会生成一个 JWT 安全令牌:
    private JwtSecurityToken GetJwtSecurityToken(List<Claim> user_claims)
    {
         string privateKey = "YOUR_PRIVATE_KEY";
         var symmetricKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(privateKey));
         var credentials = new SigningCredentials(symmetricKey, SecurityAlgorithms.HmacSha256);
    
         return new JwtSecurityToken
         (
              issuer: "ISSUER_NAME",
              audience: "AUDIENCE",
              claims: user_claims,
              signingCredentials: credentials
         );
    }
    
    1. 序列化 JWT(从第 2 步开始):
    var token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
    
    1. 将令牌发送给用户或将其添加到 cookie。

    2. 在你的startup file

    services.AddAuthentication()
        .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, config =>
        {
            config.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = "ISSUER",
                ValidAudience = "AUDIENCE",
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("YOUR_PRIVATE_KEY"))
             };
    });
    
    1. 通过添加以下内容来保护您的控制器:
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    

    就是这样。希望有人能告诉我们是否有更好的解决方案。


    更新1(添加参考):

    查看这篇文章Securing ASP.NET Core 2.0 Applications with JWTs

    【讨论】:

      【解决方案3】:

      南宇的回答非常准确,你有这些高级选项:

      • 在后端配置固定密钥并使用它验证令牌。这将工作一段时间,但如果密钥未可靠同步,并且 Auth0 更新令牌签名密钥,那么将来可能会严重损坏,可能会给您的公司带来严重问题。

      • 确保您的后端作为受信任的提供者与 Auth0 具有出站连接,以便系统能够以最简单、最标准的方式可靠地工作。

      这感觉像是人员和流程问题,而不是技术问题。我不会尝试通过代码更改来解决它。

      我怀疑 IT 管理员正试图执行一项不符合贵公司利益的过时无互联网政策。在 IT 级别,很容易仅将 Auth0 URL 列入白名单并阻止其他 URL。

      下一步,我将尝试说服您的利益相关者/老板支持标准设置 - 或许将这篇文章转发给他们。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-23
        • 2017-12-02
        • 2020-10-22
        • 2020-05-12
        • 2020-08-22
        • 2019-09-06
        • 2021-04-20
        • 2020-09-04
        相关资源
        最近更新 更多