使用带有 C# 的公钥验证 JWT

Posted

技术标签:

【中文标题】使用带有 C# 的公钥验证 JWT【英文标题】:Verifying a JWT using the public key with C# 【发布时间】:2021-08-21 00:18:33 【问题描述】:

我正在构建一个由用 C# 编写的 Azure 函数支持的 React 应用程序。我已经通过 Userfront 实现了 JWT 身份验证,该身份验证在前端运行良好,但我正在努力使用函数中的公钥验证令牌。

我尝试了很多方法,JWT-DotNet 是最新的但无济于事。

谁能提供一个工作代码示例?

这是我目前所拥有的(在创建新的 RS256 算法时出现“找不到请求的对象”的错误。):

var headers = req.Headers;
if (!headers.TryGetValue("Authorization", out var tokenHeader))
   return new StatusCodeResult(StatusCodes.Status403Forbidden);

var token = tokenHeader[0].Replace("Bearer ", "");

var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(Environment.GetEnvironmentVariable("Userfront_PublicKey"));

var urlEncoder = new JwtBase64UrlEncoder();
var publicKey = urlEncoder.Encode(plainTextBytes);

try

   IJsonSerializer serializer = new JsonNetSerializer();
   var provider = new UtcDateTimeProvider();
   IJwtValidator validator = new JwtValidator(serializer, provider);
   IJwtAlgorithm algorithm = new RS256Algorithm(new X509Certificate2(plainTextBytes));
   IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder,algorithm);

   var json = decoder.Decode(token[0], publicKey, verify: true);

catch (TokenExpiredException)
   ...
catch (SignatureVerificationException)
   ...

【问题讨论】:

您确保首先从 Authorization 标头中去除“Bearer”文本,对吧? :) 好地方!谢谢。我没有,这会给我带来一个问题。虽然目前仍然发生相同的错误:( hmm...这是一个有趣的场景..我无法从您的问题中判断出您的实际意图(实际项目范围)是否是在 azure 函数中进行此令牌验证工作,或者是否这是一个 XY 问题 - 您正在寻求有关在应用程序服务和中间件框架中设置、配置和处理的自定义实现的帮助....不过,这可能取决于触发函数.. 谢谢,@BrettCaswell。确实,在当前设置下,Azure 函数是直接从 React 应用程序调用的,所以理想情况下,我想坚持这一点。根据 Userfront 文档,可以使用 JWT DotNet,但他们实际上并没有给出示例。 我会复制并粘贴您尝试解码的确切文本并将其放入jwt.io 中,看看它是否可以解析它。 【参考方案1】:

假设环境变量“Userfront_PublicKey”包含一个 PEM 编码的 RSA 公钥,即:

-----BEGIN RSA PUBLIC KEY-----
(your base64-encoded RSA public key)
-----END RSA PUBLIC KEY-----

那么我会尝试以下方法(未测试,抱歉):

var headers = req.Headers;
if (!headers.TryGetValue("Authorization", out var tokenHeader))
    return new StatusCodeResult(StatusCodes.Status403Forbidden);

var token = tokenHeader[0].Replace("Bearer ", "");

var publicKeyPem = Environment.GetEnvironmentVariable("Userfront_PublicKey");
var publicKey = RSA.Create();
publicKey.ImportFromPem(publicKeyPem);

try

    var json = JwtBuilder.Create()
                         .WithAlgorithm(new RS256Algorithm(publicKey))
                         .MustVerifySignature()
                         .Decode(token); 

catch (TokenExpiredException)
...
catch (SignatureVerificationException)
...

【讨论】:

谢谢你。我相信它会起作用,但它需要 .net core 5 并且意味着转换许多功能,目前这将是一项艰巨的任务。

以上是关于使用带有 C# 的公钥验证 JWT的主要内容,如果未能解决你的问题,请参考以下文章

c#如何验证签名JWT?

在 C# 中使用 RS256(非对称)验证 JWT

如何使用带有公共 PEM 证书的 python PyJWT 验证 JWT?

如何使用 jwt 公钥在 Spring Boot 中验证承载访问令牌

NestJs 使用 jwt 和私钥和公钥进行身份验证

在 Spring Boot 安全性中使用公钥/私钥创建和验证 JWT 签名