JWKS-Client is a library written in Rust to decode and validate JWT tokens using a JSON Web Key Store.
Now at version 2.0. Support for async/await thanks to Genna Wingert. Requires Rust Stable 1.39 or higher
Changed to use the crate jsonwebtoken instead of performing validation inside this crate.
JWKS-Client was designed to work with a project that uses Rocket. Unfortunately, the version of Rocket in crates.io is not compatible with the version of Ring required for JWKS-Client. Until the next version of Rocket is published, consider using the following in your Cargo.toml
:
[dependencies]
jwks-client = "0.1.4"
rocket = { git = "https://github.com/jfbilodeau/Rocket", version = "0.5.0-dev"}
# Other dependencies...
[dependencies.rocket_contrib]
version = "0.5.0-dev"
git = "https://github.com/jfbilodeau/Rocket"
# Other options...
- No panic!
- Build with Rust stable (1.40)
- Designed for a production system (not an academic project)
- Concise results (see error::Type for example)
- Download key set from HTTP address
- Decode JWT tokens into header, payload and signature
- Verify token signature, expiry and not-before
- Determine when keys should be refreshed
- Uses the crate jsonwebtoken and provides the decoding features that allows with an RSA key type.
JWKS-Client was create specifically to decode GCP/Firebase JWT but should be useable with little to no modification. Contact me to propose support for different JWKS key store. Feedback, suggestions, complaints and criticism is appreciated.
The following demonstrates how to load a set of keys from an HTTP address and verify a JWT token using those keys:
use jwks_client::Error;
use jwks_client::KeyStore;
use serde::Deserialize;
#[tokio::main]
async fn main() {
let jkws_url = "https://raw.githubusercontent.com/jfbilodeau/jwks-client/0.1.8/test/test-jwks.json";
let key_set = KeyStore::new_from(jkws_url.to_owned()).await.unwrap();
// ...
let token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEifQ.eyJuYW1lIjoiQWRhIExvdmVsYWNlIiwiaXNzIjoiaHR0cHM6Ly9jaHJvbm9nZWFycy5jb20vdGVzdCIsImF1ZCI6InRlc3QiLCJhdXRoX3RpbWUiOjEwMCwidXNlcl9pZCI6InVpZDEyMyIsInN1YiI6InNidTEyMyIsImlhdCI6MjAwLCJleHAiOjUwMCwibmJmIjozMDAsImVtYWlsIjoiYWxvdmVsYWNlQGNocm9ub2dlYXJzLmNvbSJ9.eTQnwXrri_uY55fS4IygseBzzbosDM1hP153EZXzNlLH5s29kdlGt2mL_KIjYmQa8hmptt9RwKJHBtw6l4KFHvIcuif86Ix-iI2fCpqNnKyGZfgERV51NXk1THkgWj0GQB6X5cvOoFIdHa9XvgPl_rVmzXSUYDgkhd2t01FOjQeeT6OL2d9KdlQHJqAsvvKVc3wnaYYoSqv2z0IluvK93Tk1dUBU2yWXH34nX3GAVGvIoFoNRiiFfZwFlnz78G0b2fQV7B5g5F8XlNRdD1xmVZXU8X2-xh9LqRpnEakdhecciFHg0u6AyC4c00rlo_HBb69wlXajQ3R4y26Kpxn7HA";
#[derive(Deserialize)]
struct Claims {
iss: String,
name: String,
}
let validation = jsonwebtoken::Validation {
validate_nbf: true,
validate_exp: true,
algorithms: vec![jsonwebtoken::Algorithm::RS256], // only the RSA keytype is currently supported
leeway: 0,
sub: None,
aud: None,
iss: Some("https://chronogears.com/test".to_owned()),
};
match key_set.verify(token, &validation) {
Ok(jsonwebtoken::TokenData { header: _, claims: Claims { iss, name } }) => {
println!("iss={}", iss);
println!("name={}", name);
}
Err(Error { msg, kind }) => {
eprintln!("Could not verify token. Reason: {} {:?}", msg, kind);
}
}
}
-
WIP
- Breaking change: Use jsonwebtoken
-
0.2.0
- Breaking Change: Support for async/await (Thanks to Genna Wingert)
-
0.1.8
- Fixed issued jfbilodeau#1 (Thanks to Tim Schuster for reporting and assisting)
-
0.1.7
- Updated dependencies
-
0.1.6
- Added
key_set::KeyStore::should_refresh()
to test if keys should be refreshed - Added
key_set::KeyStore::refresh_interval
to determine how early keys should be refreshed before they expire - Some more documentation
- Added
-
0.1.5:
- Added
readme = "README.md"
toCargo.toml
- Added
-
0.1.4:
- Updated documentation--specifically how to use JWKS-Client with Rocket
- Added the ability to determine if keys should be refreshed from the
KeyStore
- Fixed example on this page--they are now directly from
./examples/*
-
0.1.3:
- Change the license to be MIT/Apache
- Moved demos into
./example
- Added the ability to verify if keys need to be refreshed in the keystore based on the cache-control header
-
0.1.2: (Sorry for the breaking changes)
- Rename module
jwks
tokeyset
- Renamed struct
Jwks
toKeyStore
- Expanded documentation a bit
- Fixed some demos
- Rename module
-
0.1.1: Original version
- Lots More documentation :P
- Automatically refresh keys
(Made with ❤️ with Rust)