jwtoken
A flexible utility library for encoding and decoding JSON Web Tokens (JWT).
Installation
Add jwtoken
to your Cargo.toml
:
[dependencies]
jwtoken = "0.1.5"
jwtoken = { version = "0.1.5", features = ["key-gen"] }
jwtoken = { version = "0.1.5", features = ["hs256"] }
jwtoken = { version = "0.1.5", features = ["rs256"] }
jwtoken = { version = "0.1.5", features = ["full"] }
Usage
HMAC-SHA256 (HS256)
HS256 uses a shared secret key for both signing and verification:
use jwtoken::{random_secret, Jwt, Encoder, Decoded, HS256};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct MyClaims {
sub: String,
name: String,
iat: u64,
}
fn main() -> Result<(), jwtoken::JwtError> {
let secret = random_secret();
let algorithm = HS256::new(&secret);
let claims = MyClaims {
sub: "1234567890".to_string(),
name: "John Doe".to_string(),
iat: 1516239022,
};
let token = Jwt::<Encoder, MyClaims>::new(claims)
.encode(&algorithm)?;
println!("Generated token: {}", token);
let decoded = Jwt::<Decoded, MyClaims>::decode(&token, &algorithm)?;
println!("Decoded claims: {:?}", decoded.claims());
Ok(())
}
RS256 (RSA-SHA256)
RS256 uses an RSA key pair, with the private key for signing and the public key for verification:
use jwtoken::{rsa_keypair, RS256Signer, RS256Verifier, Jwt, Encoder, Decoded};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct MyClaims {
sub: String,
name: String,
admin: bool,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (private_key, public_key) = rsa_keypair()?;
let signer = RS256Signer::new(private_key);
let verifier = RS256Verifier::new(public_key);
let claims = MyClaims {
sub: "user-id-42".to_string(),
name: "Jane Doe".to_string(),
admin: true,
};
let token = Jwt::<Encoder, MyClaims>::new(claims)
.encode(&signer)?;
println!("Generated RS256 token: {}", token);
let decoded = Jwt::<Decoded, MyClaims>::decode(&token, &verifier)?;
println!("Decoded RS256 claims: {:?}", decoded.claims());
let decoded_with_signer = Jwt::<Decoded, MyClaims>::decode(&token, &signer)?;
assert_eq!(decoded.claims(), decoded_with_signer.claims());
Ok(())
}
API Reference
JWT Encoder
#[derive(Serialize, Deserialize)]
struct MyClaims {
sub: String,
name: String,
role: String,
}
let claims = MyClaims {
sub: "user123".to_string(),
name: "John Doe".to_string(),
role: "admin".to_string(),
};
let jwt = Jwt::<Encoder, MyClaims>::new(claims)
.header("kid", "key-id-123") .encode(&algorithm)?;
JWT Decoder
let decoded = Jwt::<Decoded, MyClaims>::decode(&token, &algorithm)?;
let user_id = &decoded.claims().sub;
let name = &decoded.claims().name;
let algorithm = decoded.header("alg");
let key_id = decoded.header("kid");
Algorithms
HS256 (HMAC-SHA256)
use jwtoken::{random_secret, HS256};
let secret = random_secret();
let algorithm = HS256::new(&secret);
RS256 (RSA-SHA256)
use jwtoken::{rsa_keypair, RS256Signer, RS256Verifier};
let (private_key, public_key) = rsa_keypair().unwrap();
let signer = RS256Signer::new(private_key);
let verifier = RS256Verifier::new(public_key);
Error Handling
The library uses a custom JwtError
enum for error handling:
use jwtoken::JwtError;
match result {
Ok(token) => println!("Success: {}", token),
Err(JwtError::InvalidSignature) => println!("Invalid signature"),
Err(JwtError::InvalidFormat) => println!("Malformed JWT"),
Err(JwtError::InvalidAlgorithm) => println!("Algorithm mismatch"),
Err(JwtError::SerializationError) => println!("JSON error"),
Err(JwtError::InvalidKey) => println!("Invalid or unsupported cryptographic key"),
Err(JwtError::Custom(msg)) => println!("Custom error: {}", msg),
}