common_access_token/lib.rs
1//! # Common Access Token (CAT)
2//!
3//! A Rust implementation of the Common Access Token specification, which is based on CBOR Object Signing and Encryption (COSE).
4//!
5//! ## Overview
6//!
7//! Common Access Tokens are compact, secure tokens designed for efficient transmission in resource-constrained environments.
8//! They use CBOR encoding for smaller token sizes compared to JSON-based tokens like JWT.
9//!
10//! ## Features
11//!
12//! - CBOR-encoded tokens for compact representation
13//! - Support for both COSE_Sign1 and COSE_Mac0 structures
14//! - HMAC-SHA256 authentication
15//! - Protected and unprotected headers
16//! - Standard registered claims (issuer, subject, audience, expiration, etc.)
17//! - Custom claims with string, binary, integer, and nested map values
18//! - CAT-specific claims for URI validation (CATU), HTTP method restrictions (CATM),
19//! replay protection (CATREPLAY), and token renewal (CATR)
20//! - Comprehensive token verification including CAT-specific claim validation
21//!
22//! ## Basic Example
23//!
24//! ```rust
25//! use common_access_token::{Algorithm, KeyId, RegisteredClaims, TokenBuilder, VerificationOptions};
26//! use common_access_token::current_timestamp;
27//!
28//! // Create a key for signing and verification
29//! let key = b"my-secret-key-for-hmac-sha256";
30//! let now = current_timestamp();
31//!
32//! // Create a token
33//! let token = TokenBuilder::new()
34//! .algorithm(Algorithm::HmacSha256)
35//! .protected_key_id(KeyId::string("example-key-id"))
36//! .registered_claims(
37//! RegisteredClaims::new()
38//! .with_issuer("example-issuer")
39//! .with_subject("example-subject")
40//! .with_audience("example-audience")
41//! .with_expiration(now + 3600) // 1 hour from now
42//! )
43//! .custom_string(100, "custom-value")
44//! .sign(key)
45//! .expect("Failed to sign token");
46//!
47//! // Encode token to bytes
48//! let token_bytes = token.to_bytes().expect("Failed to encode token");
49//!
50//! // Decode and verify the token
51//! let decoded_token = common_access_token::Token::from_bytes(&token_bytes)
52//! .expect("Failed to decode token");
53//!
54//! // Verify the signature
55//! decoded_token.verify(key).expect("Failed to verify signature");
56//!
57//! // Verify the claims
58//! let options = VerificationOptions::new()
59//! .verify_exp(true)
60//! .expected_issuer("example-issuer");
61//!
62//! decoded_token.verify_claims(&options).expect("Failed to verify claims");
63//! ```
64//!
65//! ## CAT-Specific Claims Example
66//!
67//! ```rust
68//! use common_access_token::{
69//! Algorithm, KeyId, RegisteredClaims, TokenBuilder, VerificationOptions,
70//! cat_keys, catm, catr, catreplay, catu, uri_components, current_timestamp,
71//! cattprint, FingerprintType
72//! };
73//! use std::collections::BTreeMap;
74//!
75//! // Create a key for signing and verification
76//! let key = b"my-secret-key-for-hmac-sha256";
77//! let now = current_timestamp();
78//!
79//! // Create CATU claim (URI restrictions)
80//! let mut catu_components = BTreeMap::new();
81//! // Restrict to https scheme
82//! catu_components.insert(uri_components::SCHEME, catu::exact_match("https"));
83//! // Restrict to example.com host
84//! catu_components.insert(uri_components::HOST, catu::suffix_match(".example.com"));
85//! // Restrict to paths starting with /api
86//! catu_components.insert(uri_components::PATH, catu::prefix_match("/api"));
87//!
88//! // Create CATM claim (HTTP method restrictions)
89//! let allowed_methods = vec!["GET", "HEAD"];
90//!
91//! // Create a token with CAT-specific claims
92//! let token = TokenBuilder::new()
93//! .algorithm(Algorithm::HmacSha256)
94//! .protected_key_id(KeyId::string("example-key-id"))
95//! .registered_claims(
96//! RegisteredClaims::new()
97//! .with_issuer("example-issuer")
98//! .with_expiration(now + 3600)
99//! )
100//! // Add CAT-specific claims
101//! .custom_cbor(cat_keys::CATU, catu::create(catu_components))
102//! .custom_array(cat_keys::CATM, catm::create(allowed_methods))
103//! .custom_cbor(cat_keys::CATREPLAY, catreplay::prohibited())
104//! .custom_cbor(cat_keys::CATTPRINT, cattprint::create(FingerprintType::JA4, "t13d1516h2_8daaf6152771_b186095e22b6"))
105//! .sign(key)
106//! .expect("Failed to sign token");
107//!
108//! // Encode token to bytes
109//! let token_bytes = token.to_bytes().expect("Failed to encode token");
110//!
111//! // Decode and verify the token
112//! let decoded_token = common_access_token::Token::from_bytes(&token_bytes)
113//! .expect("Failed to decode token");
114//!
115//! // Verify signature
116//! decoded_token.verify(key).expect("Failed to verify signature");
117//!
118//! // Verify standard claims and CAT-specific claims
119//! let options = VerificationOptions::new()
120//! .verify_exp(true)
121//! .expected_issuer("example-issuer")
122//! // Add CAT-specific claim verification
123//! .verify_catu(true)
124//! .uri("https://api.example.com/api/users")
125//! .verify_catm(true)
126//! .http_method("GET")
127//! .verify_catreplay(true)
128//! .token_seen_before(false);
129//!
130//! decoded_token.verify_claims(&options).expect("Failed to verify all claims");
131//! ```
132
133pub mod cat_claims;
134pub mod claims;
135pub mod constants;
136pub mod error;
137pub mod header;
138pub mod token;
139pub mod utils;
140
141pub use cat_claims::{
142 catalpn, catdpop, catgeoalt, catgeocoord, catgeoiso3166, cath, catif, catifdata, catm, catnip,
143 catpor, catr, catreplay, cattpk, catu, catv, cattprint,
144};
145pub use claims::{Claims, RegisteredClaims};
146pub use constants::{
147 cat_keys, cose_algs, cose_labels, cwt_keys, match_types, renewal_params, renewal_types,
148 replay_values, uri_components, tprint_params, FingerprintType
149};
150pub use error::Error;
151pub use header::{Algorithm, CborValue, Header, HeaderMap, KeyId};
152pub use token::{Token, TokenBuilder, VerificationOptions};
153pub use utils::current_timestamp;
154
155/// Re-export minicbor for users of this crate
156pub use minicbor;
157
158#[cfg(test)]
159mod tests;