6个版本
新 0.4.1 | 2024年8月20日 |
---|---|
0.4.0 | 2024年1月30日 |
0.3.0 | 2023年11月7日 |
0.2.2 | 2023年6月6日 |
0.2.1 | 2023年1月13日 |
在密码学类别中排名第334
每月下载量339次
73KB
1K SLoC
用于basebox(以及可能的其他)的JWT验证库
概述
这个库是为了提供一种简单、直接且可靠的验证JWT的方式,这些JWT通过从URL加载的公钥集合进行验证。我们在basebox使用它来验证OpenID Connect ID Tokens(它们是JWT),使用OpenID服务器(例如Keycloak)发布的公钥集合。
它提供了以下功能
- 从URL下载一组公钥(一个JSON Web Key Set)
- 提供更新密钥集的入口点,如果需要的话
- 解析JWT并使用下载的密钥集中的密钥进行验证。
就这样。
此外,我们设计bbjwt以满足以下要求
- 无不安全代码
- 从不panic
- API中没有生命周期指定符
- 异步
- 线程安全
算法支持
下表显示了bbjwt支持的签名算法,以及它们在JWK、JWT等中的使用信息。
注意 请注意,bbjwt 0.3.0.*中已移除Ed448和ES512签名支持。
名称 | JOSE "kty" | JOSE "alg" | JOSE "curve" |
---|---|---|---|
RSA256 | RSA | RS256 | |
RSA384 | RSA | RS384 | |
RSA512 | RSA | RS512 | |
ES256 | EC | ES256 | P-256 |
ES384 | EC | ES384 | P-384 |
Ed25519 | OKP | EdDSA | Ed25519 |
不支持加密JWT。
顺便说一下,如果可以选择,请使用Ed25519。它是安全和快速的。
为什么还需要另一个Rust JWT验证库?
我们尝试了各种其他的Rust JWT库,但没有一个适合我们。问题包括复杂的API、缺乏文档和/或功能。这是我们尝试做得更好的尝试:-)
使用方法
为了验证JWT,您必须拥有发行者的公钥。使用bbjwt,您可以通过从发行者提供的URL下载它们,或者从本地缓冲区/文件中加载它们来获取它们。
从URL下载公钥
请参阅以下示例
use bbjwt::KeyStore;
#[tokio::main]
async fn main() {
// bbjwt provides a function to determine the public keyset URL by loading discovery
// info from the issuer; this is common for OpenID Connect servers.
// If you are using Keycloak, you can use this convenience function to get the discovery
// endpoint URL; all you need is the base URL and the realm name:
let discovery_url = KeyStore::keycloak_discovery_url(
"https://server.tld", "testing"
).unwrap();
// If you're not using Keycloak, the URL might be different.
let discovery_url = "https://idp-host.tld/.well-known/discovery";
// Call IdP's discovery endpoint to query the keyset URL; this is a common feature on
// OpenID Connect servers.
let keyset_url = KeyStore::idp_certs_url(discovery_url).await.unwrap();
// Now we can load the keys into a new KeyStore:
let keystore = KeyStore::new_from_url(&keyset_url).await.unwrap();
}
使用内存中的公钥
在从本地文件或缓冲区加载公钥时,您可以加载一个JWK JSON或PEM编码的文本。JWK包含识别密钥类型所需的所有信息,但针对PEM,您需要使用与密钥类型对应的函数。
请参阅以下示例
use bbjwt::{KeyStore, KeyAlgorithm, EcCurve};
#[tokio::main]
async fn main() {
// Create an empty keystore
let mut keystore = KeyStore::new().await.unwrap();
// Load public key from a JWK JSON; see
// https://openid.net/specs/draft-jones-json-web-key-03.html#ExampleJWK
let json_key = r#"
{
"kty":"RSA",
"use":"sig",
... abbreviated ...,
}"#;
// Add the key
keystore.add_key(json_key).await;
let pem_key = r#"-----BEGIN PUBLIC KEY-----
..."#;
// Load a RSA key from a PEM buffer
keystore.add_rsa_pem_key(
pem_key,
Some("key-rsa"),
KeyAlgorithm::RS256
).await.unwrap();
// Load a EC key from a PEM buffer
keystore.add_ec_pem_key(
pem_key,
Some("key-ec"),
EcCurve::P256,
KeyAlgorithm::ES256
).await.unwrap();
// Load EdDSA key from a PEM buffer
keystore.add_ec_pem_key(
pem_key,
Some("key-ed"),
EcCurve::Ed25519,
KeyAlgorithm::EdDSA
).await.unwrap();
// You can add more keys; in this case, the keys should have an ID and the JWT to be
// validated should have a "kid" claim. Otherwise, bbjwt uses the first key in the set.
}
验证JWT
JWT以Base64编码的字符串传递;有关此格式的详细信息,请参阅例如https://jwt.node.org.cn。
要验证JWT,您需要将base64编码的JWT和一个ValidationStep
向量传递给validate_jwt
。bbjwt提供了一个名为default_validations
的便利函数来创建一个默认验证步骤向量。
如果JWT有效,validate_jwt
将返回JWT包含的所有声明(头部和负载)。
示例
use bbjwt::{KeyStore, default_validations, validate_jwt};
#[tokio::main]
async fn main() {
// Create a keystore; see examples above
let keystore = KeyStore::new_from_url("https://server.tld/keyset").await.unwrap();
// Validate a JWT
let jwt = validate_jwt(
"<Base64 encoded JWT>",
&default_validations(
// required value for the "iss" claim
"https://idp.domain.url/realm/testing",
None,
None),
&keystore
)
.await
.unwrap();
// Read some claims (JWT fields)
assert_eq!(jwt.claims["nonce"].as_str().unwrap(), "UZ1BSZFvy7jKkj1o9p3r7w");
}
版权(c)2022 basebox GmbH,版权所有。
许可证:MIT
用❤️和Emacs制作 :-)
依赖项
~15–28MB
~525K SLoC