common_access_token/
lib.rs

1/*!
2# Common Access Token (CAT) for Rust
3
4A Rust implementation of the Common Access Token (CAT) specification with HMAC signatures.
5
6## Overview
7
8Common Access Token (CAT) is a token format designed for authorization and authentication
9in distributed systems, particularly for media and content delivery applications. It is based
10on the CBOR Web Token (CWT) format defined in [RFC 8392](https://tools.ietf.org/html/rfc8392)
11and uses COSE (CBOR Object Signing and Encryption) for cryptographic operations.
12
13CAT tokens are compact, secure, and designed to be efficiently processed in resource-constrained
14environments. They can be used for various purposes such as:
15
16- Authentication and authorization for content access
17- Secure communication between services
18- Session management
19- Delegation of permissions
20
21## Features
22
23This library provides:
24
25- Generation of CAT tokens with HMAC signatures (HS256)
26- Validation of CAT tokens
27- Re-signing of existing tokens to extend their lifetime
28- Support for standard CWT claims (issuer, subject, audience, expiration, etc.)
29- Support for CAT-specific claims (version, renewal, usage, data, authorization)
30- Interoperability with other CAT implementations like [node-cat](https://github.com/Eyevinn/node-cat)
31
32## Architecture
33
34The library is organized into several modules:
35
36- `cat`: Core functionality for token generation and validation
37- `claims`: Implementation of CWT and CAT-specific claims
38- `cose`: CBOR Object Signing and Encryption implementation
39- `error`: Error types and handling
40- `util`: Utility functions for encoding, decoding, and time operations
41
42## Usage Examples
43
44### Token Generation
45
46```rust
47use common_access_token::{Cat, CatGenerateOptions, CatOptions, CatValidationType, Claims};
48use std::collections::HashMap;
49
50// Create a key for token signing
51let key = hex::decode("403697de87af64611c1d32a05dab0fe1fcb715a86ab435f1ec99192d79569388").unwrap();
52let mut keys = HashMap::new();
53keys.insert("Symmetric256".to_string(), key);
54
55// Create CAT options
56let cat_options = CatOptions {
57    keys,
58    expect_cwt_tag: true,
59};
60
61// Create a CAT instance
62let cat = Cat::new(cat_options);
63
64// Create claims
65let mut claims = Claims::new();
66claims.set_issuer("example");
67claims.set_subject("user123");
68claims.set_audience("service");
69claims.set_expiration(std::time::SystemTime::now()
70    .duration_since(std::time::UNIX_EPOCH).unwrap()
71    .as_secs() as i64 + 3600); // 1 hour from now
72
73// Generate token
74let token = cat.generate(claims, &CatGenerateOptions {
75    validation_type: CatValidationType::Mac,
76    alg: "HS256".to_string(),
77    kid: "Symmetric256".to_string(),
78    generate_cwt_id: true,
79}).unwrap();
80```
81
82### Token Validation
83
84```rust
85use common_access_token::{Cat, CatGenerateOptions, CatOptions, CatValidationOptions, CatValidationType, Claims};
86use std::collections::HashMap;
87
88// First generate a token to validate
89let key = hex::decode("403697de87af64611c1d32a05dab0fe1fcb715a86ab435f1ec99192d79569388").unwrap();
90let mut keys = HashMap::new();
91keys.insert("Symmetric256".to_string(), key.clone());
92
93// Create a CAT instance
94let cat = Cat::new(CatOptions {
95    keys,
96    expect_cwt_tag: true,
97});
98
99// Create claims
100let mut claims = Claims::new();
101claims.set_issuer("example");
102claims.set_subject("user123");
103
104// Generate a token
105let token = cat.generate(claims, &CatGenerateOptions {
106    validation_type: CatValidationType::Mac,
107    alg: "HS256".to_string(),
108    kid: "Symmetric256".to_string(),
109    generate_cwt_id: true,
110}).unwrap();
111
112// Now validate the token
113let validation_options = CatValidationOptions {
114    issuer: "example".to_string(),
115    audience: None,
116};
117
118match cat.validate(&token, CatValidationType::Mac, &validation_options) {
119    Ok(claims) => {
120        println!("Token is valid!");
121        println!("Subject: {:?}", claims.get_subject());
122    }
123    Err(err) => {
124        eprintln!("Token validation failed: {}", err);
125    }
126}
127```
128
129### Token Re-signing
130
131```rust
132use common_access_token::{Cat, CatGenerateOptions, CatOptions, CatValidationOptions, CatValidationType, Claims};
133use std::collections::HashMap;
134use std::time::SystemTime;
135
136// First generate a token that we'll later re-sign
137let key = hex::decode("403697de87af64611c1d32a05dab0fe1fcb715a86ab435f1ec99192d79569388").unwrap();
138let mut keys = HashMap::new();
139keys.insert("Symmetric256".to_string(), key.clone());
140
141// Create a CAT instance
142let cat = Cat::new(CatOptions {
143    keys,
144    expect_cwt_tag: true,
145});
146
147// Create claims with a short expiration
148let mut claims = Claims::new();
149claims.set_issuer("example");
150claims.set_subject("user123");
151
152// Set expiration to 5 minutes from now
153let now = SystemTime::now()
154    .duration_since(SystemTime::UNIX_EPOCH)
155    .unwrap()
156    .as_secs() as i64;
157claims.set_expiration(now + 300); // 5 minutes
158claims.set_issued_at(now);
159
160// Generate the initial token
161let token = cat.generate(claims, &CatGenerateOptions {
162    validation_type: CatValidationType::Mac,
163    alg: "HS256".to_string(),
164    kid: "Symmetric256".to_string(),
165    generate_cwt_id: true,
166}).unwrap();
167
168// Later, when we want to extend the token's lifetime:
169
170// Validation options for the existing token
171let validation_options = CatValidationOptions {
172    issuer: "example".to_string(),
173    audience: None,
174};
175
176// Calculate new expiration time (1 hour from now)
177let new_expiration = SystemTime::now()
178    .duration_since(SystemTime::UNIX_EPOCH)
179    .unwrap()
180    .as_secs() as i64 + 3600;
181
182// Re-sign the token with the new expiration
183let new_token = cat.resign_token(
184    &token,
185    &validation_options,
186    new_expiration,
187    &CatGenerateOptions {
188        validation_type: CatValidationType::Mac,
189        alg: "HS256".to_string(),
190        kid: "Symmetric256".to_string(),
191        generate_cwt_id: true, // Generate a new CWT ID
192    }
193).unwrap();
194
195println!("Token re-signed with new expiration!");
196```
197
198## References
199
200- [CBOR Web Token (CWT) - RFC 8392](https://tools.ietf.org/html/rfc8392)
201- [CBOR Object Signing and Encryption (COSE) - RFC 8152](https://tools.ietf.org/html/rfc8152)
202- [node-cat Implementation](https://github.com/Eyevinn/node-cat)
203*/
204
205pub mod cat;
206pub mod claims;
207pub mod cose;
208pub mod error;
209pub mod util;
210
211pub use cat::{Cat, CatGenerateOptions, CatOptions, CatValidationOptions, CatValidationType};
212pub use claims::{ClaimValue, Claims};
213pub use error::Error;