cat_validation/
cat_validation.rs1use common_access_token::{
2 cat_keys, catm, catr, catreplay, catu, current_timestamp, uri_components, Algorithm, KeyId,
3 RegisteredClaims, TokenBuilder, VerificationOptions,
4};
5use std::collections::BTreeMap;
6
7fn main() {
8 let key = b"my-secret-key-for-hmac-sha256";
10 let now = current_timestamp() as i64;
11
12 let token = create_token_with_cat_claims(key, now);
14
15 let token_bytes = token.to_bytes().expect("Failed to encode token");
17 println!(
18 "Token with CAT claims encoded to {} bytes",
19 token_bytes.len()
20 );
21
22 let decoded_token =
24 common_access_token::Token::from_bytes(&token_bytes).expect("Failed to decode token");
25
26 decoded_token
28 .verify(key)
29 .expect("Failed to verify signature");
30
31 validate_catu_claim(&decoded_token);
33 validate_catm_claim(&decoded_token);
34 validate_catreplay_claim(&decoded_token);
35}
36
37fn create_token_with_cat_claims(key: &[u8], now: i64) -> common_access_token::Token {
39 println!("Creating token with CAT-specific claims...");
40
41 let mut catu_components = BTreeMap::new();
43
44 catu_components.insert(uri_components::SCHEME, catu::exact_match("https"));
46
47 catu_components.insert(uri_components::HOST, catu::suffix_match(".example.com"));
49
50 catu_components.insert(uri_components::PATH, catu::prefix_match("/api"));
52
53 catu_components.insert(uri_components::EXTENSION, catu::exact_match(".json"));
55
56 println!(" Added CATU claim with URI restrictions");
57
58 let allowed_methods = vec!["GET", "HEAD", "OPTIONS"];
60 println!(" Added CATM claim allowing methods: {:?}", allowed_methods);
61
62 let renewal_params = catr::automatic_renewal(3600, Some(now + 3000));
64 println!(" Added CATR claim with automatic renewal");
65
66 println!(" Added CATREPLAY claim prohibiting token replay");
68
69 TokenBuilder::new()
71 .algorithm(Algorithm::HmacSha256)
72 .protected_key_id(KeyId::string("example-key-id"))
73 .registered_claims(
74 RegisteredClaims::new()
75 .with_issuer("example-issuer")
76 .with_subject("example-subject")
77 .with_audience("example-audience")
78 .with_expiration(now as u64 + 3600) .with_not_before(now as u64)
80 .with_issued_at(now as u64)
81 .with_cti(b"token-id-1234".to_vec()),
82 )
83 .custom_cbor(cat_keys::CATU, catu::create(catu_components))
85 .custom_cbor(cat_keys::CATR, catr::create(renewal_params))
86 .custom_cbor(cat_keys::CATREPLAY, catreplay::prohibited())
87 .custom_array(cat_keys::CATM, catm::create(allowed_methods))
88 .sign(key)
89 .expect("Failed to sign token")
90}
91
92fn validate_catu_claim(token: &common_access_token::Token) {
94 println!("\nValidating CATU (URI) claim:");
95
96 let valid_uri = "https://api.example.com/api/users.json";
98 let invalid_scheme_uri = "http://api.example.com/api/users.json";
99 let invalid_host_uri = "https://api.other-site.com/api/users.json";
100 let invalid_path_uri = "https://api.example.com/users.json";
101 let invalid_extension_uri = "https://api.example.com/api/users.xml";
102
103 let options = VerificationOptions::new().verify_catu(true).uri(valid_uri);
105
106 match token.verify_claims(&options) {
107 Ok(_) => println!(" VALID URI: {}", valid_uri),
108 Err(e) => println!(
109 " ERROR: {} should be valid, but got error: {}",
110 valid_uri, e
111 ),
112 }
113
114 let invalid_scheme_options = VerificationOptions::new()
116 .verify_catu(true)
117 .uri(invalid_scheme_uri);
118
119 match token.verify_claims(&invalid_scheme_options) {
120 Ok(_) => println!(
121 " ERROR: {} should be invalid (wrong scheme)",
122 invalid_scheme_uri
123 ),
124 Err(e) => println!(
125 " INVALID URI (as expected): {} - Error: {}",
126 invalid_scheme_uri, e
127 ),
128 }
129
130 let invalid_host_options = VerificationOptions::new()
132 .verify_catu(true)
133 .uri(invalid_host_uri);
134
135 match token.verify_claims(&invalid_host_options) {
136 Ok(_) => println!(
137 " ERROR: {} should be invalid (wrong host)",
138 invalid_host_uri
139 ),
140 Err(e) => println!(
141 " INVALID URI (as expected): {} - Error: {}",
142 invalid_host_uri, e
143 ),
144 }
145
146 let invalid_path_options = VerificationOptions::new()
148 .verify_catu(true)
149 .uri(invalid_path_uri);
150
151 match token.verify_claims(&invalid_path_options) {
152 Ok(_) => println!(
153 " ERROR: {} should be invalid (wrong path)",
154 invalid_path_uri
155 ),
156 Err(e) => println!(
157 " INVALID URI (as expected): {} - Error: {}",
158 invalid_path_uri, e
159 ),
160 }
161
162 let invalid_extension_options = VerificationOptions::new()
164 .verify_catu(true)
165 .uri(invalid_extension_uri);
166
167 match token.verify_claims(&invalid_extension_options) {
168 Ok(_) => println!(
169 " ERROR: {} should be invalid (wrong extension)",
170 invalid_extension_uri
171 ),
172 Err(e) => println!(
173 " INVALID URI (as expected): {} - Error: {}",
174 invalid_extension_uri, e
175 ),
176 }
177}
178
179fn validate_catm_claim(token: &common_access_token::Token) {
181 println!("\nValidating CATM (HTTP Methods) claim:");
182
183 for method in &["GET", "HEAD", "OPTIONS"] {
185 let options = VerificationOptions::new()
186 .verify_catm(true)
187 .http_method(*method);
188
189 match token.verify_claims(&options) {
190 Ok(_) => println!(" VALID METHOD: {}", method),
191 Err(e) => println!(" ERROR: {} should be valid, but got error: {}", method, e),
192 }
193 }
194
195 for method in &["POST", "PUT", "DELETE", "PATCH"] {
197 let options = VerificationOptions::new()
198 .verify_catm(true)
199 .http_method(*method);
200
201 match token.verify_claims(&options) {
202 Ok(_) => println!(" ERROR: {} should be invalid method", method),
203 Err(e) => println!(" INVALID METHOD (as expected): {} - Error: {}", method, e),
204 }
205 }
206}
207
208fn validate_catreplay_claim(token: &common_access_token::Token) {
210 println!("\nValidating CATREPLAY claim:");
211
212 let options_not_seen = VerificationOptions::new()
214 .verify_catreplay(true)
215 .token_seen_before(false);
216
217 match token.verify_claims(&options_not_seen) {
218 Ok(_) => println!(" VALID: Token not seen before is accepted (as expected)"),
219 Err(e) => println!(
220 " ERROR: Token not seen before should be valid, but got error: {}",
221 e
222 ),
223 }
224
225 let options_seen = VerificationOptions::new()
227 .verify_catreplay(true)
228 .token_seen_before(true);
229
230 match token.verify_claims(&options_seen) {
231 Ok(_) => println!(" ERROR: Token seen before should be rejected"),
232 Err(e) => println!(
233 " INVALID (as expected): Token seen before is rejected - Error: {}",
234 e
235 ),
236 }
237}