pub struct Token {
pub header: Header,
pub claims: Claims,
pub signature: Vec<u8>,
/* private fields */
}Expand description
Common Access Token structure
Fields§
§header: HeaderToken header
claims: ClaimsToken claims
signature: Vec<u8>Token signature
Implementations§
Source§impl Token
impl Token
Sourcepub fn new(header: Header, claims: Claims, signature: Vec<u8>) -> Self
pub fn new(header: Header, claims: Claims, signature: Vec<u8>) -> Self
Create a new token with the given header, claims, and signature
Sourcepub fn to_bytes(&self) -> Result<Vec<u8>, Error>
pub fn to_bytes(&self) -> Result<Vec<u8>, Error>
Encode the token to CBOR bytes
Examples found in repository?
7fn main() {
8 // Create a key for signing and verification
9 let key = b"my-secret-key-for-hmac-sha256";
10 let now = current_timestamp() as i64;
11
12 // Create a token with multiple CAT-specific claims
13 let token = create_token_with_cat_claims(key, now);
14
15 // Encode token to bytes
16 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 // Decode the token
23 let decoded_token =
24 common_access_token::Token::from_bytes(&token_bytes).expect("Failed to decode token");
25
26 // Verify signature
27 decoded_token
28 .verify(key)
29 .expect("Failed to verify signature");
30
31 // Demonstrate different CAT-specific claim validations
32 validate_catu_claim(&decoded_token);
33 validate_catm_claim(&decoded_token);
34 validate_catreplay_claim(&decoded_token);
35}More examples
7fn main() {
8 // Create a key for signing and verification
9 let key = b"my-secret-key-for-hmac-sha256";
10
11 // Create a token with CAT-specific claims
12 let token = create_token_with_cat_claims(key);
13
14 // Encode token to bytes
15 let token_bytes = token.to_bytes().expect("Failed to encode token");
16 println!("Token encoded to {} bytes", token_bytes.len());
17
18 // Decode and verify the token
19 let decoded_token =
20 common_access_token::Token::from_bytes(&token_bytes).expect("Failed to decode token");
21
22 // Verify the signature
23 decoded_token
24 .verify(key)
25 .expect("Failed to verify signature");
26
27 // Verify the claims
28 let options = VerificationOptions::new()
29 .verify_exp(true)
30 .expected_issuer("example-issuer");
31
32 decoded_token
33 .verify_claims(&options)
34 .expect("Failed to verify claims");
35
36 // Print token information
37 print_token_info(&decoded_token);
38}7fn main() {
8 // Secret key for signing and verification
9 let key = b"my-secret-key-for-hmac-sha256";
10
11 // Create a token with both string and binary key ID examples
12 let string_kid_token = create_token_with_string_kid(key);
13 let binary_kid_token = create_token_with_binary_kid(key);
14 let nested_map_token = create_token_with_nested_map(key);
15
16 // Encode tokens to bytes
17 let string_kid_token_bytes = string_kid_token.to_bytes().expect("Failed to encode token");
18 let binary_kid_token_bytes = binary_kid_token.to_bytes().expect("Failed to encode token");
19 let nested_map_token_bytes = nested_map_token.to_bytes().expect("Failed to encode token");
20
21 println!(
22 "Token with string key ID encoded as {} bytes",
23 string_kid_token_bytes.len()
24 );
25 println!(
26 "Token with binary key ID encoded as {} bytes",
27 binary_kid_token_bytes.len()
28 );
29 println!(
30 "Token with nested map encoded as {} bytes",
31 nested_map_token_bytes.len()
32 );
33
34 // Decode and verify tokens
35 verify_token(&string_kid_token_bytes, key, "string-key-example");
36 verify_token(&binary_kid_token_bytes, key, "binary-key-example");
37 verify_nested_map_token(&nested_map_token_bytes, key);
38}20fn main() {
21 let key = b"my-secret-key-for-hmac-sha256";
22 let now = current_timestamp();
23
24 println!("=== Extended CAT Claims Example ===\n");
25
26 // Example 1: Token with probability of rejection (CATPOR)
27 println!("1. Creating token with CATPOR (25% rejection probability)");
28 let token_with_catpor = TokenBuilder::new()
29 .algorithm(Algorithm::HmacSha256)
30 .protected_key_id(KeyId::string("key-1"))
31 .registered_claims(
32 RegisteredClaims::new()
33 .with_issuer("example-issuer")
34 .with_expiration(now + 3600),
35 )
36 .custom_cbor(cat_keys::CATPOR, catpor::create(25))
37 .sign(key)
38 .expect("Failed to sign token");
39
40 println!(" ✓ Token created with CATPOR: 25% rejection probability\n");
41
42 // Example 2: Token with network IP restrictions (CATNIP)
43 println!("2. Creating token with CATNIP (IP restrictions)");
44 let token_with_catnip = TokenBuilder::new()
45 .algorithm(Algorithm::HmacSha256)
46 .protected_key_id(KeyId::string("key-2"))
47 .registered_claims(
48 RegisteredClaims::new()
49 .with_issuer("example-issuer")
50 .with_expiration(now + 3600),
51 )
52 .custom_array(
53 cat_keys::CATNIP,
54 catnip::create(vec!["192.168.1.0/24", "10.0.0.0/8"]),
55 )
56 .sign(key)
57 .expect("Failed to sign token");
58
59 println!(" ✓ Token created with CATNIP: 192.168.1.0/24, 10.0.0.0/8\n");
60
61 // Example 3: Token with ALPN restrictions (CATALPN)
62 println!("3. Creating token with CATALPN (HTTP/2 only)");
63 let token_with_catalpn = TokenBuilder::new()
64 .algorithm(Algorithm::HmacSha256)
65 .protected_key_id(KeyId::string("key-3"))
66 .registered_claims(
67 RegisteredClaims::new()
68 .with_issuer("example-issuer")
69 .with_expiration(now + 3600),
70 )
71 .custom_array(cat_keys::CATALPN, catalpn::http2_only())
72 .sign(key)
73 .expect("Failed to sign token");
74
75 println!(" ✓ Token created with CATALPN: h2 only\n");
76
77 // Example 4: Token with HTTP header requirements (CATH)
78 println!("4. Creating token with CATH (custom headers)");
79 let mut headers = BTreeMap::new();
80 headers.insert("X-API-Key", "secret-api-key");
81 headers.insert("X-Client-Version", "1.0");
82
83 let token_with_cath = TokenBuilder::new()
84 .algorithm(Algorithm::HmacSha256)
85 .protected_key_id(KeyId::string("key-4"))
86 .registered_claims(
87 RegisteredClaims::new()
88 .with_issuer("example-issuer")
89 .with_expiration(now + 3600),
90 )
91 .custom_cbor(cat_keys::CATH, cath::create(headers))
92 .sign(key)
93 .expect("Failed to sign token");
94
95 println!(" ✓ Token created with CATH: X-API-Key, X-Client-Version\n");
96
97 // Example 5: Token with geographic restrictions (CATGEO*)
98 println!("5. Creating token with geographic restrictions");
99 let token_with_geo = TokenBuilder::new()
100 .algorithm(Algorithm::HmacSha256)
101 .protected_key_id(KeyId::string("key-5"))
102 .registered_claims(
103 RegisteredClaims::new()
104 .with_issuer("example-issuer")
105 .with_expiration(now + 3600),
106 )
107 // Country restriction
108 .custom_array(cat_keys::CATGEOISO3166, catgeoiso3166::create(vec!["US"]))
109 // Coordinate restriction (New York City with 5km radius)
110 .custom_cbor(
111 cat_keys::CATGEOCOORD,
112 catgeocoord::with_radius(40.7128, -74.0060, 5000),
113 )
114 // Altitude restriction (0-1000 meters)
115 .custom_cbor(cat_keys::CATGEOALT, catgeoalt::range(0, 1000))
116 .sign(key)
117 .expect("Failed to sign token");
118
119 println!(" ✓ Token created with CATGEOISO3166: US");
120 println!(" ✓ Token created with CATGEOCOORD: NYC (40.7128, -74.0060) ±5km");
121 println!(" ✓ Token created with CATGEOALT: 0-1000m\n");
122
123 // Example 6: Token with TLS public key pinning (CATTPK)
124 println!("6. Creating token with CATTPK (TLS key pinning)");
125 // In a real scenario, this would be the SHA-256 hash of a certificate's public key
126 let public_key_hash = vec![
127 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
128 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab,
129 0xcd, 0xef,
130 ];
131
132 let token_with_cattpk = TokenBuilder::new()
133 .algorithm(Algorithm::HmacSha256)
134 .protected_key_id(KeyId::string("key-6"))
135 .registered_claims(
136 RegisteredClaims::new()
137 .with_issuer("example-issuer")
138 .with_expiration(now + 3600),
139 )
140 .custom_cbor(cat_keys::CATTPK, cattpk::create(public_key_hash.clone()))
141 .sign(key)
142 .expect("Failed to sign token");
143
144 println!(" ✓ Token created with CATTPK: public key hash (32 bytes)\n");
145
146 // Example 7: Token with DPoP settings (CATDPOP)
147 println!("7. Creating token with CATDPOP (DPoP required)");
148 let token_with_catdpop = TokenBuilder::new()
149 .algorithm(Algorithm::HmacSha256)
150 .protected_key_id(KeyId::string("key-7"))
151 .registered_claims(
152 RegisteredClaims::new()
153 .with_issuer("example-issuer")
154 .with_expiration(now + 3600),
155 )
156 .custom_cbor(cat_keys::CATDPOP, catdpop::required())
157 .sign(key)
158 .expect("Failed to sign token");
159
160 println!(" ✓ Token created with CATDPOP: DPoP required\n");
161
162 // Example 8: Token with conditional logic (CATIF/CATIFDATA)
163 println!("8. Creating token with CATIF and CATIFDATA");
164 let mut condition = BTreeMap::new();
165 condition.insert(0, common_access_token::CborValue::Text("role".to_string()));
166 condition.insert(
167 1,
168 common_access_token::CborValue::Text("equals".to_string()),
169 );
170 condition.insert(2, common_access_token::CborValue::Text("admin".to_string()));
171
172 let mut if_data = BTreeMap::new();
173 if_data.insert(0, common_access_token::CborValue::Text("role".to_string()));
174 if_data.insert(1, common_access_token::CborValue::Text("admin".to_string()));
175
176 let token_with_catif = TokenBuilder::new()
177 .algorithm(Algorithm::HmacSha256)
178 .protected_key_id(KeyId::string("key-8"))
179 .registered_claims(
180 RegisteredClaims::new()
181 .with_issuer("example-issuer")
182 .with_expiration(now + 3600),
183 )
184 .custom_cbor(cat_keys::CATIF, catif::create(condition))
185 .custom_cbor(cat_keys::CATIFDATA, catifdata::create(if_data))
186 .sign(key)
187 .expect("Failed to sign token");
188
189 println!(" ✓ Token created with CATIF: conditional logic");
190 println!(" ✓ Token created with CATIFDATA: role=admin\n");
191
192 // Example 9: Comprehensive token with multiple CAT claims
193 println!("9. Creating comprehensive token with multiple CAT claims");
194 let comprehensive_token = TokenBuilder::new()
195 .algorithm(Algorithm::HmacSha256)
196 .protected_key_id(KeyId::string("comprehensive-key"))
197 .registered_claims(
198 RegisteredClaims::new()
199 .with_issuer("secure-service")
200 .with_subject("user-12345")
201 .with_audience("api.example.com")
202 .with_expiration(now + 7200),
203 )
204 .custom_cbor(cat_keys::CATV, catv::with_version(1))
205 .custom_cbor(cat_keys::CATPOR, catpor::create(10))
206 .custom_array(cat_keys::CATNIP, catnip::single("203.0.113.0/24"))
207 .custom_array(cat_keys::CATALPN, catalpn::create(vec!["h2", "http/1.1"]))
208 .custom_array(cat_keys::CATGEOISO3166, catgeoiso3166::create(vec!["US"]))
209 .sign(key)
210 .expect("Failed to sign token");
211
212 println!(" ✓ Comprehensive token created with:");
213 println!(" - CATV: version 1");
214 println!(" - CATPOR: 10% rejection probability");
215 println!(" - CATNIP: 203.0.113.0/24");
216 println!(" - CATALPN: h2, http/1.1");
217 println!(" - CATGEOISO3166: US");
218
219 // Verify all tokens can be encoded
220 println!("\n=== Verification ===");
221 let tokens = vec![
222 ("CATPOR", &token_with_catpor),
223 ("CATNIP", &token_with_catnip),
224 ("CATALPN", &token_with_catalpn),
225 ("CATH", &token_with_cath),
226 ("CATGEO*", &token_with_geo),
227 ("CATTPK", &token_with_cattpk),
228 ("CATDPOP", &token_with_catdpop),
229 ("CATIF", &token_with_catif),
230 ("Comprehensive", &comprehensive_token),
231 ];
232
233 for (name, token) in tokens {
234 let token_bytes = token.to_bytes().expect("Failed to encode token");
235 println!("✓ {} token encoded ({} bytes)", name, token_bytes.len());
236 }
237
238 println!("\n=== All Extended CAT Claims Examples Completed Successfully ===");
239}Sourcepub fn from_bytes(bytes: &[u8]) -> Result<Self, Error>
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error>
Decode a token from CBOR bytes
This function supports both COSE_Sign1 (tag 18) and COSE_Mac0 (tag 17) structures, as well as custom tags. It will automatically skip any tags and process the underlying CBOR array.
Examples found in repository?
7fn main() {
8 // Create a key for signing and verification
9 let key = b"my-secret-key-for-hmac-sha256";
10 let now = current_timestamp() as i64;
11
12 // Create a token with multiple CAT-specific claims
13 let token = create_token_with_cat_claims(key, now);
14
15 // Encode token to bytes
16 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 // Decode the token
23 let decoded_token =
24 common_access_token::Token::from_bytes(&token_bytes).expect("Failed to decode token");
25
26 // Verify signature
27 decoded_token
28 .verify(key)
29 .expect("Failed to verify signature");
30
31 // Demonstrate different CAT-specific claim validations
32 validate_catu_claim(&decoded_token);
33 validate_catm_claim(&decoded_token);
34 validate_catreplay_claim(&decoded_token);
35}More examples
7fn main() {
8 // Create a key for signing and verification
9 let key = b"my-secret-key-for-hmac-sha256";
10
11 // Create a token with CAT-specific claims
12 let token = create_token_with_cat_claims(key);
13
14 // Encode token to bytes
15 let token_bytes = token.to_bytes().expect("Failed to encode token");
16 println!("Token encoded to {} bytes", token_bytes.len());
17
18 // Decode and verify the token
19 let decoded_token =
20 common_access_token::Token::from_bytes(&token_bytes).expect("Failed to decode token");
21
22 // Verify the signature
23 decoded_token
24 .verify(key)
25 .expect("Failed to verify signature");
26
27 // Verify the claims
28 let options = VerificationOptions::new()
29 .verify_exp(true)
30 .expected_issuer("example-issuer");
31
32 decoded_token
33 .verify_claims(&options)
34 .expect("Failed to verify claims");
35
36 // Print token information
37 print_token_info(&decoded_token);
38}124fn verify_token(token_bytes: &[u8], key: &[u8], expected_token_type: &str) {
125 // Decode the token
126 let token = match common_access_token::Token::from_bytes(token_bytes) {
127 Ok(token) => token,
128 Err(err) => {
129 println!("Failed to decode {} token: {}", expected_token_type, err);
130 return;
131 }
132 };
133
134 // Verify the signature
135 if let Err(err) = token.verify(key) {
136 println!(
137 "Failed to verify {} token signature: {}",
138 expected_token_type, err
139 );
140 return;
141 }
142
143 // Verify the claims
144 let options = VerificationOptions::new()
145 .verify_exp(true)
146 .verify_nbf(true)
147 .expected_issuer("example-issuer")
148 .expected_audience("example-audience");
149
150 if let Err(err) = token.verify_claims(&options) {
151 println!(
152 "Failed to verify {} token claims: {}",
153 expected_token_type, err
154 );
155 return;
156 }
157
158 // Get the key ID
159 let kid = token.header.key_id().expect("No key ID in token");
160 let kid_str = match &kid {
161 KeyId::Binary(data) => format!("Binary key ID: {:?}", data),
162 KeyId::String(data) => format!("String key ID: {}", data),
163 };
164
165 println!(
166 "Successfully verified {} token ({})",
167 expected_token_type, kid_str
168 );
169
170 // Print some claims
171 if let Some(iss) = &token.claims.registered.iss {
172 println!(" Issuer: {}", iss);
173 }
174 if let Some(sub) = &token.claims.registered.sub {
175 println!(" Subject: {}", sub);
176 }
177 if let Some(exp) = token.claims.registered.exp {
178 println!(
179 " Expires at: {} (in {} seconds)",
180 exp,
181 exp - current_timestamp()
182 );
183 }
184}
185
186/// Verify a token with a nested map claim
187fn verify_nested_map_token(token_bytes: &[u8], key: &[u8]) {
188 // Decode the token
189 let token = match common_access_token::Token::from_bytes(token_bytes) {
190 Ok(token) => token,
191 Err(err) => {
192 println!("Failed to decode nested map token: {}", err);
193 return;
194 }
195 };
196
197 // Verify the signature
198 if let Err(err) = token.verify(key) {
199 println!("Failed to verify nested map token signature: {}", err);
200 return;
201 }
202
203 // Verify the claims
204 let options = VerificationOptions::new()
205 .verify_exp(true)
206 .verify_nbf(true)
207 .expected_issuer("example-issuer")
208 .expected_audience("example-audience");
209
210 if let Err(err) = token.verify_claims(&options) {
211 println!("Failed to verify nested map token claims: {}", err);
212 return;
213 }
214
215 println!("Successfully verified nested map token");
216
217 // Check for the nested map claim
218 if let Some(CborValue::Map(map)) = token.claims.custom.get(&200) {
219 println!(" Found nested map claim with {} entries", map.len());
220
221 // Print first level entries
222 if let Some(CborValue::Text(text)) = map.get(&1) {
223 println!(" Entry 1: Text = {}", text);
224 }
225
226 if let Some(CborValue::Integer(num)) = map.get(&2) {
227 println!(" Entry 2: Integer = {}", num);
228 }
229
230 if let Some(CborValue::Bytes(bytes)) = map.get(&3) {
231 println!(" Entry 3: Bytes = {:?}", bytes);
232 }
233
234 // Check for second level map
235 if let Some(CborValue::Map(second_map)) = map.get(&4) {
236 println!(" Entry 4: Nested map with {} entries", second_map.len());
237
238 if let Some(CborValue::Text(text)) = second_map.get(&1) {
239 println!(" Nested Entry 1: Text = {}", text);
240 }
241
242 if let Some(CborValue::Integer(num)) = second_map.get(&2) {
243 println!(" Nested Entry 2: Integer = {}", num);
244 }
245 }
246 } else {
247 println!(" Nested map claim not found!");
248 }
249}Sourcepub fn verify(&self, key: &[u8]) -> Result<(), Error>
pub fn verify(&self, key: &[u8]) -> Result<(), Error>
Verify the token signature
This function supports both COSE_Sign1 and COSE_Mac0 structures. It will first try to verify the signature using the COSE_Sign1 structure, and if that fails, it will try the COSE_Mac0 structure.
Examples found in repository?
7fn main() {
8 // Create a key for signing and verification
9 let key = b"my-secret-key-for-hmac-sha256";
10 let now = current_timestamp() as i64;
11
12 // Create a token with multiple CAT-specific claims
13 let token = create_token_with_cat_claims(key, now);
14
15 // Encode token to bytes
16 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 // Decode the token
23 let decoded_token =
24 common_access_token::Token::from_bytes(&token_bytes).expect("Failed to decode token");
25
26 // Verify signature
27 decoded_token
28 .verify(key)
29 .expect("Failed to verify signature");
30
31 // Demonstrate different CAT-specific claim validations
32 validate_catu_claim(&decoded_token);
33 validate_catm_claim(&decoded_token);
34 validate_catreplay_claim(&decoded_token);
35}More examples
7fn main() {
8 // Create a key for signing and verification
9 let key = b"my-secret-key-for-hmac-sha256";
10
11 // Create a token with CAT-specific claims
12 let token = create_token_with_cat_claims(key);
13
14 // Encode token to bytes
15 let token_bytes = token.to_bytes().expect("Failed to encode token");
16 println!("Token encoded to {} bytes", token_bytes.len());
17
18 // Decode and verify the token
19 let decoded_token =
20 common_access_token::Token::from_bytes(&token_bytes).expect("Failed to decode token");
21
22 // Verify the signature
23 decoded_token
24 .verify(key)
25 .expect("Failed to verify signature");
26
27 // Verify the claims
28 let options = VerificationOptions::new()
29 .verify_exp(true)
30 .expected_issuer("example-issuer");
31
32 decoded_token
33 .verify_claims(&options)
34 .expect("Failed to verify claims");
35
36 // Print token information
37 print_token_info(&decoded_token);
38}124fn verify_token(token_bytes: &[u8], key: &[u8], expected_token_type: &str) {
125 // Decode the token
126 let token = match common_access_token::Token::from_bytes(token_bytes) {
127 Ok(token) => token,
128 Err(err) => {
129 println!("Failed to decode {} token: {}", expected_token_type, err);
130 return;
131 }
132 };
133
134 // Verify the signature
135 if let Err(err) = token.verify(key) {
136 println!(
137 "Failed to verify {} token signature: {}",
138 expected_token_type, err
139 );
140 return;
141 }
142
143 // Verify the claims
144 let options = VerificationOptions::new()
145 .verify_exp(true)
146 .verify_nbf(true)
147 .expected_issuer("example-issuer")
148 .expected_audience("example-audience");
149
150 if let Err(err) = token.verify_claims(&options) {
151 println!(
152 "Failed to verify {} token claims: {}",
153 expected_token_type, err
154 );
155 return;
156 }
157
158 // Get the key ID
159 let kid = token.header.key_id().expect("No key ID in token");
160 let kid_str = match &kid {
161 KeyId::Binary(data) => format!("Binary key ID: {:?}", data),
162 KeyId::String(data) => format!("String key ID: {}", data),
163 };
164
165 println!(
166 "Successfully verified {} token ({})",
167 expected_token_type, kid_str
168 );
169
170 // Print some claims
171 if let Some(iss) = &token.claims.registered.iss {
172 println!(" Issuer: {}", iss);
173 }
174 if let Some(sub) = &token.claims.registered.sub {
175 println!(" Subject: {}", sub);
176 }
177 if let Some(exp) = token.claims.registered.exp {
178 println!(
179 " Expires at: {} (in {} seconds)",
180 exp,
181 exp - current_timestamp()
182 );
183 }
184}
185
186/// Verify a token with a nested map claim
187fn verify_nested_map_token(token_bytes: &[u8], key: &[u8]) {
188 // Decode the token
189 let token = match common_access_token::Token::from_bytes(token_bytes) {
190 Ok(token) => token,
191 Err(err) => {
192 println!("Failed to decode nested map token: {}", err);
193 return;
194 }
195 };
196
197 // Verify the signature
198 if let Err(err) = token.verify(key) {
199 println!("Failed to verify nested map token signature: {}", err);
200 return;
201 }
202
203 // Verify the claims
204 let options = VerificationOptions::new()
205 .verify_exp(true)
206 .verify_nbf(true)
207 .expected_issuer("example-issuer")
208 .expected_audience("example-audience");
209
210 if let Err(err) = token.verify_claims(&options) {
211 println!("Failed to verify nested map token claims: {}", err);
212 return;
213 }
214
215 println!("Successfully verified nested map token");
216
217 // Check for the nested map claim
218 if let Some(CborValue::Map(map)) = token.claims.custom.get(&200) {
219 println!(" Found nested map claim with {} entries", map.len());
220
221 // Print first level entries
222 if let Some(CborValue::Text(text)) = map.get(&1) {
223 println!(" Entry 1: Text = {}", text);
224 }
225
226 if let Some(CborValue::Integer(num)) = map.get(&2) {
227 println!(" Entry 2: Integer = {}", num);
228 }
229
230 if let Some(CborValue::Bytes(bytes)) = map.get(&3) {
231 println!(" Entry 3: Bytes = {:?}", bytes);
232 }
233
234 // Check for second level map
235 if let Some(CborValue::Map(second_map)) = map.get(&4) {
236 println!(" Entry 4: Nested map with {} entries", second_map.len());
237
238 if let Some(CborValue::Text(text)) = second_map.get(&1) {
239 println!(" Nested Entry 1: Text = {}", text);
240 }
241
242 if let Some(CborValue::Integer(num)) = second_map.get(&2) {
243 println!(" Nested Entry 2: Integer = {}", num);
244 }
245 }
246 } else {
247 println!(" Nested map claim not found!");
248 }
249}Sourcepub fn verify_claims(&self, options: &VerificationOptions) -> Result<(), Error>
pub fn verify_claims(&self, options: &VerificationOptions) -> Result<(), Error>
Verify the token claims
Examples found in repository?
7fn main() {
8 // Create a key for signing and verification
9 let key = b"my-secret-key-for-hmac-sha256";
10
11 // Create a token with CAT-specific claims
12 let token = create_token_with_cat_claims(key);
13
14 // Encode token to bytes
15 let token_bytes = token.to_bytes().expect("Failed to encode token");
16 println!("Token encoded to {} bytes", token_bytes.len());
17
18 // Decode and verify the token
19 let decoded_token =
20 common_access_token::Token::from_bytes(&token_bytes).expect("Failed to decode token");
21
22 // Verify the signature
23 decoded_token
24 .verify(key)
25 .expect("Failed to verify signature");
26
27 // Verify the claims
28 let options = VerificationOptions::new()
29 .verify_exp(true)
30 .expected_issuer("example-issuer");
31
32 decoded_token
33 .verify_claims(&options)
34 .expect("Failed to verify claims");
35
36 // Print token information
37 print_token_info(&decoded_token);
38}More examples
124fn verify_token(token_bytes: &[u8], key: &[u8], expected_token_type: &str) {
125 // Decode the token
126 let token = match common_access_token::Token::from_bytes(token_bytes) {
127 Ok(token) => token,
128 Err(err) => {
129 println!("Failed to decode {} token: {}", expected_token_type, err);
130 return;
131 }
132 };
133
134 // Verify the signature
135 if let Err(err) = token.verify(key) {
136 println!(
137 "Failed to verify {} token signature: {}",
138 expected_token_type, err
139 );
140 return;
141 }
142
143 // Verify the claims
144 let options = VerificationOptions::new()
145 .verify_exp(true)
146 .verify_nbf(true)
147 .expected_issuer("example-issuer")
148 .expected_audience("example-audience");
149
150 if let Err(err) = token.verify_claims(&options) {
151 println!(
152 "Failed to verify {} token claims: {}",
153 expected_token_type, err
154 );
155 return;
156 }
157
158 // Get the key ID
159 let kid = token.header.key_id().expect("No key ID in token");
160 let kid_str = match &kid {
161 KeyId::Binary(data) => format!("Binary key ID: {:?}", data),
162 KeyId::String(data) => format!("String key ID: {}", data),
163 };
164
165 println!(
166 "Successfully verified {} token ({})",
167 expected_token_type, kid_str
168 );
169
170 // Print some claims
171 if let Some(iss) = &token.claims.registered.iss {
172 println!(" Issuer: {}", iss);
173 }
174 if let Some(sub) = &token.claims.registered.sub {
175 println!(" Subject: {}", sub);
176 }
177 if let Some(exp) = token.claims.registered.exp {
178 println!(
179 " Expires at: {} (in {} seconds)",
180 exp,
181 exp - current_timestamp()
182 );
183 }
184}
185
186/// Verify a token with a nested map claim
187fn verify_nested_map_token(token_bytes: &[u8], key: &[u8]) {
188 // Decode the token
189 let token = match common_access_token::Token::from_bytes(token_bytes) {
190 Ok(token) => token,
191 Err(err) => {
192 println!("Failed to decode nested map token: {}", err);
193 return;
194 }
195 };
196
197 // Verify the signature
198 if let Err(err) = token.verify(key) {
199 println!("Failed to verify nested map token signature: {}", err);
200 return;
201 }
202
203 // Verify the claims
204 let options = VerificationOptions::new()
205 .verify_exp(true)
206 .verify_nbf(true)
207 .expected_issuer("example-issuer")
208 .expected_audience("example-audience");
209
210 if let Err(err) = token.verify_claims(&options) {
211 println!("Failed to verify nested map token claims: {}", err);
212 return;
213 }
214
215 println!("Successfully verified nested map token");
216
217 // Check for the nested map claim
218 if let Some(CborValue::Map(map)) = token.claims.custom.get(&200) {
219 println!(" Found nested map claim with {} entries", map.len());
220
221 // Print first level entries
222 if let Some(CborValue::Text(text)) = map.get(&1) {
223 println!(" Entry 1: Text = {}", text);
224 }
225
226 if let Some(CborValue::Integer(num)) = map.get(&2) {
227 println!(" Entry 2: Integer = {}", num);
228 }
229
230 if let Some(CborValue::Bytes(bytes)) = map.get(&3) {
231 println!(" Entry 3: Bytes = {:?}", bytes);
232 }
233
234 // Check for second level map
235 if let Some(CborValue::Map(second_map)) = map.get(&4) {
236 println!(" Entry 4: Nested map with {} entries", second_map.len());
237
238 if let Some(CborValue::Text(text)) = second_map.get(&1) {
239 println!(" Nested Entry 1: Text = {}", text);
240 }
241
242 if let Some(CborValue::Integer(num)) = second_map.get(&2) {
243 println!(" Nested Entry 2: Integer = {}", num);
244 }
245 }
246 } else {
247 println!(" Nested map claim not found!");
248 }
249}93fn validate_catu_claim(token: &common_access_token::Token) {
94 println!("\nValidating CATU (URI) claim:");
95
96 // Define URIs to test
97 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 // Test valid URI
104 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 // Test invalid scheme
115 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 // Test invalid host
131 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 // Test invalid path
147 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 // Test invalid extension
163 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
179/// Validate the CATM claim against different HTTP methods
180fn validate_catm_claim(token: &common_access_token::Token) {
181 println!("\nValidating CATM (HTTP Methods) claim:");
182
183 // Test allowed methods
184 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 // Test disallowed methods
196 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
208/// Validate the CATREPLAY claim
209fn validate_catreplay_claim(token: &common_access_token::Token) {
210 println!("\nValidating CATREPLAY claim:");
211
212 // Test with token not seen before (should pass)
213 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 // Test with token seen before (should fail with replay prohibited)
226 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}Sourcepub fn is_expired(&self) -> bool
pub fn is_expired(&self) -> bool
Check if the token has expired
Returns true if the token has an expiration claim and the current time is at or after it.
Returns false if the token has no expiration claim or if it hasn’t expired yet.
§Example
use common_access_token::{TokenBuilder, Algorithm, RegisteredClaims, current_timestamp};
let key = b"my-secret-key";
let now = current_timestamp();
// Token that expires in 1 hour
let token = TokenBuilder::new()
.algorithm(Algorithm::HmacSha256)
.registered_claims(RegisteredClaims::new().with_expiration(now + 3600))
.sign(key)
.unwrap();
assert!(!token.is_expired());Sourcepub fn expires_in(&self) -> Option<Duration>
pub fn expires_in(&self) -> Option<Duration>
Get the duration until token expiration
Returns Some(Duration) if the token has an expiration claim and hasn’t expired yet.
Returns None if the token has no expiration claim or has already expired.
§Example
use common_access_token::{TokenBuilder, Algorithm, RegisteredClaims, current_timestamp};
let key = b"my-secret-key";
let now = current_timestamp();
let token = TokenBuilder::new()
.algorithm(Algorithm::HmacSha256)
.registered_claims(RegisteredClaims::new().with_expiration(now + 3600))
.sign(key)
.unwrap();
if let Some(duration) = token.expires_in() {
println!("Token expires in {} seconds", duration.as_secs());
}Sourcepub fn is_valid_yet(&self) -> bool
pub fn is_valid_yet(&self) -> bool
Check if the token is valid based on the not-before (nbf) claim
Returns true if the token has no nbf claim or if the current time is at or after it.
Returns false if the token has an nbf claim and the current time is before it.
§Example
use common_access_token::{TokenBuilder, Algorithm, RegisteredClaims, current_timestamp};
let key = b"my-secret-key";
let now = current_timestamp();
let token = TokenBuilder::new()
.algorithm(Algorithm::HmacSha256)
.registered_claims(RegisteredClaims::new().with_not_before(now))
.sign(key)
.unwrap();
assert!(token.is_valid_yet());Sourcepub fn issuer(&self) -> Option<&str>
pub fn issuer(&self) -> Option<&str>
Get the issuer claim value
§Example
use common_access_token::{TokenBuilder, Algorithm, RegisteredClaims};
let key = b"my-secret-key";
let token = TokenBuilder::new()
.algorithm(Algorithm::HmacSha256)
.registered_claims(RegisteredClaims::new().with_issuer("example-issuer"))
.sign(key)
.unwrap();
assert_eq!(token.issuer(), Some("example-issuer"));Sourcepub fn subject(&self) -> Option<&str>
pub fn subject(&self) -> Option<&str>
Get the subject claim value
§Example
use common_access_token::{TokenBuilder, Algorithm, RegisteredClaims};
let key = b"my-secret-key";
let token = TokenBuilder::new()
.algorithm(Algorithm::HmacSha256)
.registered_claims(RegisteredClaims::new().with_subject("user-123"))
.sign(key)
.unwrap();
assert_eq!(token.subject(), Some("user-123"));Sourcepub fn audience(&self) -> Option<&str>
pub fn audience(&self) -> Option<&str>
Get the audience claim value
§Example
use common_access_token::{TokenBuilder, Algorithm, RegisteredClaims};
let key = b"my-secret-key";
let token = TokenBuilder::new()
.algorithm(Algorithm::HmacSha256)
.registered_claims(RegisteredClaims::new().with_audience("api-service"))
.sign(key)
.unwrap();
assert_eq!(token.audience(), Some("api-service"));Sourcepub fn expiration(&self) -> Option<u64>
pub fn expiration(&self) -> Option<u64>
Get the expiration timestamp
Sourcepub fn not_before(&self) -> Option<u64>
pub fn not_before(&self) -> Option<u64>
Get the not-before timestamp
Sourcepub fn get_custom_string(&self, key: i32) -> Option<&str>
pub fn get_custom_string(&self, key: i32) -> Option<&str>
Get a custom claim as a string
Returns Some(&str) if the claim exists and is a text value, None otherwise.
§Example
use common_access_token::{TokenBuilder, Algorithm};
let key = b"my-secret-key";
let token = TokenBuilder::new()
.algorithm(Algorithm::HmacSha256)
.custom_string(100, "custom-value")
.sign(key)
.unwrap();
assert_eq!(token.get_custom_string(100), Some("custom-value"));
assert_eq!(token.get_custom_string(999), None);Sourcepub fn get_custom_int(&self, key: i32) -> Option<i64>
pub fn get_custom_int(&self, key: i32) -> Option<i64>
Get a custom claim as an integer
Returns Some(i64) if the claim exists and is an integer value, None otherwise.
§Example
use common_access_token::{TokenBuilder, Algorithm};
let key = b"my-secret-key";
let token = TokenBuilder::new()
.algorithm(Algorithm::HmacSha256)
.custom_int(100, 42)
.sign(key)
.unwrap();
assert_eq!(token.get_custom_int(100), Some(42));
assert_eq!(token.get_custom_int(999), None);Sourcepub fn get_custom_binary(&self, key: i32) -> Option<&[u8]>
pub fn get_custom_binary(&self, key: i32) -> Option<&[u8]>
Get a custom claim as binary data
Returns Some(&[u8]) if the claim exists and is a bytes value, None otherwise.
§Example
use common_access_token::{TokenBuilder, Algorithm};
let key = b"my-secret-key";
let data = vec![1, 2, 3, 4];
let token = TokenBuilder::new()
.algorithm(Algorithm::HmacSha256)
.custom_binary(100, data.clone())
.sign(key)
.unwrap();
assert_eq!(token.get_custom_binary(100), Some(data.as_slice()));
assert_eq!(token.get_custom_binary(999), None);Sourcepub fn get_custom_claim(&self, key: i32) -> Option<&CborValue>
pub fn get_custom_claim(&self, key: i32) -> Option<&CborValue>
Get a reference to a custom claim value
Returns Some(&CborValue) if the claim exists, None otherwise.
§Example
use common_access_token::{TokenBuilder, Algorithm, CborValue};
let key = b"my-secret-key";
let token = TokenBuilder::new()
.algorithm(Algorithm::HmacSha256)
.custom_string(100, "value")
.sign(key)
.unwrap();
if let Some(CborValue::Text(s)) = token.get_custom_claim(100) {
assert_eq!(s, "value");
}Sourcepub fn has_custom_claim(&self, key: i32) -> bool
pub fn has_custom_claim(&self, key: i32) -> bool
Check if a custom claim exists
§Example
use common_access_token::{TokenBuilder, Algorithm};
let key = b"my-secret-key";
let token = TokenBuilder::new()
.algorithm(Algorithm::HmacSha256)
.custom_string(100, "value")
.sign(key)
.unwrap();
assert!(token.has_custom_claim(100));
assert!(!token.has_custom_claim(999));