jwtoken 0.1.5

A flexible utility library for encoding and decoding JSON Web Tokens (JWT).
Documentation

jwtoken

A flexible utility library for encoding and decoding JSON Web Tokens (JWT).

Installation

Add jwtoken to your Cargo.toml:

[dependencies]
# Basic usage
jwtoken = "0.1.5"

# With key generation utilities (for random secrets, RSA keypairs)
jwtoken = { version = "0.1.5", features = ["key-gen"] }

# Enable HS256 algorithm
jwtoken = { version = "0.1.5", features = ["hs256"] }

# Enable RS256 algorithm
jwtoken = { version = "0.1.5", features = ["rs256"] }

# Enable all features
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> {
    // Requires the "key-gen" feature
    let secret = random_secret();
    let algorithm = HS256::new(&secret);

    let claims = MyClaims {
        sub: "1234567890".to_string(),
        name: "John Doe".to_string(),
        iat: 1516239022,
    };

    // Encoding a JWT
    let token = Jwt::<Encoder, MyClaims>::new(claims)
        .encode(&algorithm)?;
    println!("Generated token: {}", token);

    // Decoding and verifying the same JWT
    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>> {
    // Requires the "key-gen" and "rs256" features
    let (private_key, public_key) = rsa_keypair()?;

    // Create a signer with the private key
    let signer = RS256Signer::new(private_key);
    // Create a verifier with the public key
    let verifier = RS256Verifier::new(public_key);

    let claims = MyClaims {
        sub: "user-id-42".to_string(),
        name: "Jane Doe".to_string(),
        admin: true,
    };

    // Encoding a JWT
    let token = Jwt::<Encoder, MyClaims>::new(claims)
        .encode(&signer)?;
    println!("Generated RS256 token: {}", token);

    // Decoding and verifying the same JWT with the public key
    let decoded = Jwt::<Decoded, MyClaims>::decode(&token, &verifier)?;
    println!("Decoded RS256 claims: {:?}", decoded.claims());

    // The signer also implements Verifier, so it can be used for verification too
    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")                        // Add custom header
    .encode(&algorithm)?;                               // Sign and encode to string

JWT Decoder

let decoded = Jwt::<Decoded, MyClaims>::decode(&token, &algorithm)?;

// Access claims directly through the struct
let user_id = &decoded.claims().sub;
let name = &decoded.claims().name;

// Access headers
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};

// Requires the "key-gen" and "rs256" features
let (private_key, public_key) = rsa_keypair().unwrap();

// For signing
let signer = RS256Signer::new(private_key);

// For verifying
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),
}