Expand description
§Common Access Token (CAT) for Rust
A Rust implementation of the Common Access Token (CAT) specification with HMAC signatures.
§Overview
Common Access Token (CAT) is a token format designed for authorization and authentication in distributed systems, particularly for media and content delivery applications. It is based on the CBOR Web Token (CWT) format defined in RFC 8392 and uses COSE (CBOR Object Signing and Encryption) for cryptographic operations.
CAT tokens are compact, secure, and designed to be efficiently processed in resource-constrained environments. They can be used for various purposes such as:
- Authentication and authorization for content access
- Secure communication between services
- Session management
- Delegation of permissions
§Features
This library provides:
- Generation of CAT tokens with HMAC signatures (HS256)
- Validation of CAT tokens
- Re-signing of existing tokens to extend their lifetime
- Support for standard CWT claims (issuer, subject, audience, expiration, etc.)
- Support for CAT-specific claims (version, renewal, usage, data, authorization)
- Interoperability with other CAT implementations like node-cat
§Architecture
The library is organized into several modules:
cat
: Core functionality for token generation and validationclaims
: Implementation of CWT and CAT-specific claimscose
: CBOR Object Signing and Encryption implementationerror
: Error types and handlingutil
: Utility functions for encoding, decoding, and time operations
§Usage Examples
§Token Generation
use common_access_token::{Cat, CatGenerateOptions, CatOptions, CatValidationType, Claims};
use std::collections::HashMap;
// Create a key for token signing
let key = hex::decode("403697de87af64611c1d32a05dab0fe1fcb715a86ab435f1ec99192d79569388").unwrap();
let mut keys = HashMap::new();
keys.insert("Symmetric256".to_string(), key);
// Create CAT options
let cat_options = CatOptions {
keys,
expect_cwt_tag: true,
};
// Create a CAT instance
let cat = Cat::new(cat_options);
// Create claims
let mut claims = Claims::new();
claims.set_issuer("example");
claims.set_subject("user123");
claims.set_audience("service");
claims.set_expiration(std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH).unwrap()
.as_secs() as i64 + 3600); // 1 hour from now
// Generate token
let token = cat.generate(claims, &CatGenerateOptions {
validation_type: CatValidationType::Mac,
alg: "HS256".to_string(),
kid: "Symmetric256".to_string(),
generate_cwt_id: true,
}).unwrap();
§Token Validation
use common_access_token::{Cat, CatGenerateOptions, CatOptions, CatValidationOptions, CatValidationType, Claims};
use std::collections::HashMap;
// First generate a token to validate
let key = hex::decode("403697de87af64611c1d32a05dab0fe1fcb715a86ab435f1ec99192d79569388").unwrap();
let mut keys = HashMap::new();
keys.insert("Symmetric256".to_string(), key.clone());
// Create a CAT instance
let cat = Cat::new(CatOptions {
keys,
expect_cwt_tag: true,
});
// Create claims
let mut claims = Claims::new();
claims.set_issuer("example");
claims.set_subject("user123");
// Generate a token
let token = cat.generate(claims, &CatGenerateOptions {
validation_type: CatValidationType::Mac,
alg: "HS256".to_string(),
kid: "Symmetric256".to_string(),
generate_cwt_id: true,
}).unwrap();
// Now validate the token
let validation_options = CatValidationOptions {
issuer: "example".to_string(),
audience: None,
};
match cat.validate(&token, CatValidationType::Mac, &validation_options) {
Ok(claims) => {
println!("Token is valid!");
println!("Subject: {:?}", claims.get_subject());
}
Err(err) => {
eprintln!("Token validation failed: {}", err);
}
}
§Token Re-signing
use common_access_token::{Cat, CatGenerateOptions, CatOptions, CatValidationOptions, CatValidationType, Claims};
use std::collections::HashMap;
use std::time::SystemTime;
// First generate a token that we'll later re-sign
let key = hex::decode("403697de87af64611c1d32a05dab0fe1fcb715a86ab435f1ec99192d79569388").unwrap();
let mut keys = HashMap::new();
keys.insert("Symmetric256".to_string(), key.clone());
// Create a CAT instance
let cat = Cat::new(CatOptions {
keys,
expect_cwt_tag: true,
});
// Create claims with a short expiration
let mut claims = Claims::new();
claims.set_issuer("example");
claims.set_subject("user123");
// Set expiration to 5 minutes from now
let now = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs() as i64;
claims.set_expiration(now + 300); // 5 minutes
claims.set_issued_at(now);
// Generate the initial token
let token = cat.generate(claims, &CatGenerateOptions {
validation_type: CatValidationType::Mac,
alg: "HS256".to_string(),
kid: "Symmetric256".to_string(),
generate_cwt_id: true,
}).unwrap();
// Later, when we want to extend the token's lifetime:
// Validation options for the existing token
let validation_options = CatValidationOptions {
issuer: "example".to_string(),
audience: None,
};
// Calculate new expiration time (1 hour from now)
let new_expiration = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs() as i64 + 3600;
// Re-sign the token with the new expiration
let new_token = cat.resign_token(
&token,
&validation_options,
new_expiration,
&CatGenerateOptions {
validation_type: CatValidationType::Mac,
alg: "HS256".to_string(),
kid: "Symmetric256".to_string(),
generate_cwt_id: true, // Generate a new CWT ID
}
).unwrap();
println!("Token re-signed with new expiration!");
§References
Re-exports§
pub use cat::Cat;
pub use cat::CatGenerateOptions;
pub use cat::CatOptions;
pub use cat::CatValidationOptions;
pub use cat::CatValidationType;
pub use claims::ClaimValue;
pub use claims::Claims;
pub use error::Error;