ASP.NET CORE如何使用JWKS来做认证和授权

JWKS是JSON Web Keys的缩写。如果API Service使用第三方的JWT Token来做认证和授权,那么通常第三方会提供一个JWKS地址,这个地址里有用来验证token的公钥。

下面是从 okta 取到的一个 JWKS 的内容示例。我们可以看到这里有两个RSA RS256 公钥。

{
  "keys": [
    {
      "kty": "RSA",
      "alg": "RS256",
      "kid": "hE2MW0jokw9QCkomGHA9zNAxnxIUc_vCVGmdc0DyE1U",
      "use": "sig",
      "e": "AQAB",
      "n": "p4s6EnKfkDU8fVh6QWOcWEDvBzFQO6EKx0URotAjj-3yakrRvhS7O9CYx6QUY8URjHfc3vgW5Do86Fgf0AcJVk_UnKhn_K4_MIzvSBspX8lIHKa7BZIstW9CcfRVtCQ1o8uhcJdRBPZ9SvqJZsK-zkIukARiqezH90tFKaDN1mYx3b9t0hVF6d6RtSZUwRphqpr7c9A_ySVT44QXYzHfuojypxlUSqx5pu4bwEedIlsyYNArzB3wdBfUXYM-8W5kiB5ntVWCPLLFrv4DilHGpMsAcrLn1iEFC0F-4skU-kkyhe3uw8cnjGXCbaOZnC6dJ1BsUkwYsS53o5rRsTt-xw"
    },
    {
      "kty": "RSA",
      "alg": "RS256",
      "kid": "Z6RuPqgZz9RVgZWEvVXvbUtu9o4sFmkE03DpcXrnJZ8",
      "use": "sig",
      "e": "AQAB",
      "n": "i223012Y_-gKCki2CkH4Xt3nk7P74Dliq6TolKWRs13nqTL69VMR_u3ewJ0Fuhe7odF_mxHs-kKe88AG_tQgSpxfsWoa0Cqa6cdudbe3Xq55Vgj2ghyF2pRAZCNU983--Kbfqxi2WyMeNnL8FD2us6euB-TWVfE4OL20p0PJbg46uMhjLgefXrOYY1sqrvGr_D2Jb4hHcaA0CY7RF8bYh4YV3ExJW2zH8bFBN0wnQnsCDtdLtL-ud_X_52ttQ2a2_VnUDabw6imEZ-ydmjjwtRPDFO8gvoGsyTiN7pgvbo4M4iePK02_Z_xLmwnsqiXP59NP_BTjOhksYBqUNO_YLQ"
    }
  ]
}

ASP.NET CORE 是通过支持 OpenId 协议来支持 JWKS 的,如果开发者只使用到 JWKS,那么开发者需要自己修改 OpenId 的参数来支持 JWKS 或者写单独的代码通过手动下载公钥和设置 TokenValidationParameters.IssuerSigningKeys 来解决问题。

幸运的是强大的开源社区给我们提供了解决方案,使用 Nuget 安装 NetDevPack.JwtExtensions,然后在 StartUp.ConfigureServices 里使用类似于下面的代码就可以简单的使用 JWKS 了。

// JWKS
            var jwksUrl = this.Configuration.GetValue<string>("Authentication:Jwks_uri");
            var issuer = this.Configuration.GetValue<string>("Authentication:ValidIssuer");
            var validateIssuer = this.Configuration.GetValue<bool>("Authentication:ValidateIssuer");

            services.AddAuthentication(o => 
                {
                    o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddJwtBearer(options =>
                {                    
                    // 加上下面的cert选项,你自己签名的证书也可以通过了
                    var httpClientHandler = new HttpClientHandler();
                    httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;

                    options.SetJwksOptions(new JwkOptions(jwksUrl));
                    options.RequireHttpsMetadata = false;
                    options.SaveToken = true;
                    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidateIssuer = validateIssuer,
                        ValidIssuer = issuer,
                        ValidateAudience = false,
                        ValidateLifetime = true,
                        RequireExpirationTime = true
                    };
                });

注意Github上只说使用 options.SetJwksOptions(new JwkOptions(jwksUrl)) 就可以了,实际上是不行的,如果不设置 TokenValidationParameters 相关的参数,你可能会看到类似下面的错误。切记!另外,证书是自己签名的,就需要加上 HttpClientHandler.DangerousAcceptAnyServerCertificateValidator 这句话,要不会看到 ssl 连接错误。
The issuer is invalid
最后别忘了在 Startup.Configure 里加上

         public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVersionDescriptionProvider provider)
        {
        	...
        	
            app.UseAuthentication();            
            app.UseAuthorization();
            
            ...
		}

参考资料:
https://github.com/NetDevPack/Security.JwtExtensions

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

surfirst

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值