common_access_token/
cat_claims.rs

1//! # CAT-specific Claims
2//!
3//! This module provides helper functions and structures for working with
4//! Common Access Token (CAT) specific claims as defined in the CAT specification.
5//!
6//! ## Available CAT Claims
7//!
8//! - **CATU** (Common Access Token URI) - limits the URI to which the token can provide access
9//! - **CATR** (Common Access Token Renewal) - instructions for token renewal
10//! - **CATM** (Common Access Token Methods) - limits HTTP methods
11//! - **CATREPLAY** - controls token replay behavior
12//! - **CATV** (Common Access Token Version) - CAT specification version
13//! - **CATPOR** (Common Access Token Probability of Rejection) - probabilistic rate limiting
14//! - **CATNIP** (Common Access Token Network IP) - IP address restrictions
15//! - **CATALPN** (Common Access Token ALPN) - TLS ALPN protocol restrictions
16//! - **CATH** (Common Access Token Header) - HTTP header requirements
17//! - **CATGEOISO3166** - geographic country/region restrictions
18//! - **CATGEOCOORD** - geographic coordinate restrictions
19//! - **CATGEOALT** - altitude restrictions
20//! - **CATTPK** (Common Access Token TLS Public Key) - TLS public key pinning
21//! - **CATDPOP** (Common Access Token DPoP Settings) - DPoP configuration
22//! - **CATIF** (Common Access Token If) - conditional logic
23//! - **CATIFDATA** (Common Access Token If Data) - data for conditional evaluation
24//! - **CATTPRINT** (Common Access Token TLS Fingerprint) - TLS fingerprint restrictions
25//!
26//! ## CATU Claim (URI Validation)
27//!
28//! The CATU claim allows you to specify URI component restrictions. For example:
29//!
30//! ```rust
31//! use common_access_token::{catu, uri_components, cat_keys};
32//! use std::collections::BTreeMap;
33//!
34//! // Create a CATU claim for URI validation
35//! let mut catu_components = BTreeMap::new();
36//!
37//! // Restrict to https scheme
38//! catu_components.insert(uri_components::SCHEME, catu::exact_match("https"));
39//!
40//! // Restrict to example.com host
41//! catu_components.insert(uri_components::HOST, catu::suffix_match(".example.com"));
42//!
43//! // Restrict to paths starting with /api
44//! catu_components.insert(uri_components::PATH, catu::prefix_match("/api"));
45//!
46//! // Create the CATU claim
47//! let catu_claim = catu::create(catu_components);
48//! ```
49//!
50//! ## CATM Claim (HTTP Methods)
51//!
52//! The CATM claim restricts which HTTP methods are allowed:
53//!
54//! ```rust
55//! use common_access_token::{catm, cat_keys};
56//!
57//! // Create a CATM claim allowing only GET and HEAD methods
58//! let allowed_methods = vec!["GET", "HEAD"];
59//! let catm_claim = catm::create(allowed_methods);
60//! ```
61//!
62//! ## CATREPLAY Claim (Replay Protection)
63//!
64//! The CATREPLAY claim controls token replay behavior:
65//!
66//! ```rust
67//! use common_access_token::{catreplay, cat_keys};
68//!
69//! // Create a CATREPLAY claim that prohibits token reuse
70//! let catreplay_claim = catreplay::prohibited();
71//!
72//! // Or allow token reuse
73//! let catreplay_permitted = catreplay::permitted();
74//!
75//! // Or enable reuse detection
76//! let catreplay_detect = catreplay::reuse_detection();
77//! ```
78//!
79//! ## CATR Claim (Token Renewal)
80//!
81//! The CATR claim provides instructions for token renewal:
82//!
83//! ```rust
84//! use common_access_token::{catr, cat_keys};
85//! use common_access_token::current_timestamp;
86//!
87//! let now = current_timestamp();
88//!
89//! // Create an automatic renewal claim
90//! // This extends expiration by 3600 seconds with a deadline 3000 seconds from now
91//! let renewal_params = catr::automatic_renewal(3600, Some((now + 3000) as i64));
92//! let catr_claim = catr::create(renewal_params);
93//!
94//! // Or create a cookie-based renewal claim
95//! let cookie_renewal = catr::cookie_renewal(
96//!     3600,
97//!     Some((now + 3000) as i64),
98//!     Some("session"),
99//!     Some(vec!["Secure", "HttpOnly"])
100//! );
101//! ```
102//!
103//! ## CATTPRINT Claim (TLS Fingerprint)
104//!
105//! The CATTPRINT claim provides instructions for validating a TLS Fingerprint:
106//!
107//! ```rust
108//! use common_access_token::{cattprint, FingerprintType};
109//!
110//! // Create a tls fingerprint claim
111//! // Possible fingerprint-type values: JA3, JA4, JA4S, JA4H, JA4L, JA4X, JA4SSH, JA4T, JA4TS, JA4TScan
112//! // Example JA4 value: t13d1516h2_8daaf6152771_b186095e22b6
113//! let cattprint_claim = cattprint::create(FingerprintType::JA4, "t13d1516h2_8daaf6152771_b186095e22b6");
114//! ```
115
116use crate::header::CborValue;
117use std::collections::BTreeMap;
118
119/// CAT-specific claim keys
120pub mod keys {
121    use crate::constants::cat_keys;
122
123    /// Common Access Token Replay (catreplay) claim key
124    pub const CATREPLAY: i32 = cat_keys::CATREPLAY;
125    /// Common Access Token Probability of Rejection (catpor) claim key
126    pub const CATPOR: i32 = cat_keys::CATPOR;
127    /// Common Access Token Version (catv) claim key
128    pub const CATV: i32 = cat_keys::CATV;
129    /// Common Access Token Network IP (catnip) claim key
130    pub const CATNIP: i32 = cat_keys::CATNIP;
131    /// Common Access Token URI (catu) claim key
132    pub const CATU: i32 = cat_keys::CATU;
133    /// Common Access Token Methods (catm) claim key
134    pub const CATM: i32 = cat_keys::CATM;
135    /// Common Access Token ALPN (catalpn) claim key
136    pub const CATALPN: i32 = cat_keys::CATALPN;
137    /// Common Access Token Header (cath) claim key
138    pub const CATH: i32 = cat_keys::CATH;
139    /// Common Access Token Geographic ISO3166 (catgeoiso3166) claim key
140    pub const CATGEOISO3166: i32 = cat_keys::CATGEOISO3166;
141    /// Common Access Token Geographic Coordinate (catgeocoord) claim key
142    pub const CATGEOCOORD: i32 = cat_keys::CATGEOCOORD;
143    /// Common Access Token Altitude (catgeoalt) claim key
144    pub const CATGEOALT: i32 = cat_keys::CATGEOALT;
145    /// Common Access Token TLS Public Key (cattpk) claim key
146    pub const CATTPK: i32 = cat_keys::CATTPK;
147    /// Common Access Token If Data (catifdata) claim key
148    pub const CATIFDATA: i32 = cat_keys::CATIFDATA;
149    /// Common Access Token DPoP Settings (catdpop) claim key
150    pub const CATDPOP: i32 = cat_keys::CATDPOP;
151    /// Common Access Token If (catif) claim key
152    pub const CATIF: i32 = cat_keys::CATIF;
153    /// Common Access Token Renewal (catr) claim key
154    pub const CATR: i32 = cat_keys::CATR;
155    /// Common Access Token TLS Fingerprint (cattprint) claim key
156    pub const CATTPRINT: i32 = cat_keys::CATTPRINT;
157}
158
159/// Helper functions for creating CATTPRINT (Common Access Token TLS Fingerprint) claims
160pub mod cattprint {
161    use super::*;
162    use crate::{constants::tprint_params, FingerprintType};
163
164    pub fn create(fingerprint_type: FingerprintType, fingerprint_value: &str) -> CborValue {
165        let mut params = BTreeMap::new();
166        params.insert(tprint_params::FINGERPRINT_TYPE, CborValue::Integer(fingerprint_type as i64));
167        params.insert(tprint_params::FINGERPRINT_VALUE, CborValue::Text(fingerprint_value.to_string()));
168        CborValue::Map(params)
169    }
170}
171
172/// Helper functions for creating CATU (Common Access Token URI) claims
173pub mod catu {
174    use super::*;
175    use crate::constants::match_types;
176
177    /// Creates a CATU claim with the specified URI component restrictions
178    pub fn create(components: BTreeMap<i32, BTreeMap<i32, CborValue>>) -> CborValue {
179        let mut map = BTreeMap::new();
180        for (component_key, match_map) in components {
181            let mut inner_map = BTreeMap::new();
182            for (match_type, match_value) in match_map {
183                inner_map.insert(match_type, match_value);
184            }
185            map.insert(component_key, CborValue::Map(inner_map));
186        }
187        CborValue::Map(map)
188    }
189
190    /// Creates a match condition for exact text matching
191    pub fn exact_match(text: &str) -> BTreeMap<i32, CborValue> {
192        let mut map = BTreeMap::new();
193        map.insert(match_types::EXACT, CborValue::Text(text.to_string()));
194        map
195    }
196
197    /// Creates a match condition for prefix matching
198    pub fn prefix_match(prefix: &str) -> BTreeMap<i32, CborValue> {
199        let mut map = BTreeMap::new();
200        map.insert(match_types::PREFIX, CborValue::Text(prefix.to_string()));
201        map
202    }
203
204    /// Creates a match condition for suffix matching
205    pub fn suffix_match(suffix: &str) -> BTreeMap<i32, CborValue> {
206        let mut map = BTreeMap::new();
207        map.insert(match_types::SUFFIX, CborValue::Text(suffix.to_string()));
208        map
209    }
210
211    /// Creates a match condition for contains matching
212    pub fn contains_match(text: &str) -> BTreeMap<i32, CborValue> {
213        let mut map = BTreeMap::new();
214        map.insert(match_types::CONTAINS, CborValue::Text(text.to_string()));
215        map
216    }
217
218    /// Creates a match condition for regex matching
219    pub fn regex_match(pattern: &str, groups: Vec<Option<String>>) -> BTreeMap<i32, CborValue> {
220        let mut map = BTreeMap::new();
221
222        let mut array = vec![CborValue::Text(pattern.to_string())];
223        for group in groups {
224            match group {
225                Some(text) => array.push(CborValue::Text(text)),
226                None => array.push(CborValue::Null),
227            }
228        }
229
230        map.insert(match_types::REGEX, CborValue::Array(array));
231        map
232    }
233
234    /// Creates a match condition for SHA-256 matching
235    pub fn sha256_match(hash: Vec<u8>) -> BTreeMap<i32, CborValue> {
236        let mut map = BTreeMap::new();
237        map.insert(match_types::SHA256, CborValue::Bytes(hash));
238        map
239    }
240
241    /// Creates a match condition for SHA-512/256 matching
242    pub fn sha512_256_match(hash: Vec<u8>) -> BTreeMap<i32, CborValue> {
243        let mut map = BTreeMap::new();
244        map.insert(match_types::SHA512_256, CborValue::Bytes(hash));
245        map
246    }
247}
248
249/// Helper functions for creating CATR (Common Access Token Renewal) claims
250pub mod catr {
251    use super::*;
252    use crate::constants::{renewal_params, renewal_types};
253
254    /// Creates a CATR claim with the specified renewal parameters
255    pub fn create(params: BTreeMap<i32, CborValue>) -> CborValue {
256        CborValue::Map(params)
257    }
258
259    /// Creates an automatic renewal claim
260    pub fn automatic_renewal(exp_add: i64, deadline: Option<i64>) -> BTreeMap<i32, CborValue> {
261        let mut map = BTreeMap::new();
262        map.insert(
263            renewal_params::TYPE,
264            CborValue::Integer(renewal_types::AUTOMATIC as i64),
265        );
266        map.insert(renewal_params::EXPADD, CborValue::Integer(exp_add));
267
268        if let Some(deadline_value) = deadline {
269            map.insert(renewal_params::DEADLINE, CborValue::Integer(deadline_value));
270        }
271
272        map
273    }
274
275    /// Creates a cookie renewal claim
276    pub fn cookie_renewal(
277        exp_add: i64,
278        deadline: Option<i64>,
279        cookie_name: Option<&str>,
280        additional_params: Option<Vec<&str>>,
281    ) -> BTreeMap<i32, CborValue> {
282        let mut map = BTreeMap::new();
283        map.insert(
284            renewal_params::TYPE,
285            CborValue::Integer(renewal_types::COOKIE as i64),
286        );
287        map.insert(renewal_params::EXPADD, CborValue::Integer(exp_add));
288
289        if let Some(deadline_value) = deadline {
290            map.insert(renewal_params::DEADLINE, CborValue::Integer(deadline_value));
291        }
292
293        if let Some(name) = cookie_name {
294            map.insert(
295                renewal_params::COOKIE_NAME,
296                CborValue::Text(name.to_string()),
297            );
298        }
299
300        if let Some(params) = additional_params {
301            let params_array: Vec<CborValue> = params
302                .into_iter()
303                .map(|s| CborValue::Text(s.to_string()))
304                .collect();
305            map.insert(
306                renewal_params::COOKIE_PARAMS,
307                CborValue::Array(params_array),
308            );
309        }
310
311        map
312    }
313
314    /// Creates a header renewal claim
315    pub fn header_renewal(
316        exp_add: i64,
317        deadline: Option<i64>,
318        header_name: Option<&str>,
319        additional_params: Option<Vec<&str>>,
320    ) -> BTreeMap<i32, CborValue> {
321        let mut map = BTreeMap::new();
322        map.insert(
323            renewal_params::TYPE,
324            CborValue::Integer(renewal_types::HEADER as i64),
325        );
326        map.insert(renewal_params::EXPADD, CborValue::Integer(exp_add));
327
328        if let Some(deadline_value) = deadline {
329            map.insert(renewal_params::DEADLINE, CborValue::Integer(deadline_value));
330        }
331
332        if let Some(name) = header_name {
333            map.insert(
334                renewal_params::HEADER_NAME,
335                CborValue::Text(name.to_string()),
336            );
337        }
338
339        if let Some(params) = additional_params {
340            let params_array: Vec<CborValue> = params
341                .into_iter()
342                .map(|s| CborValue::Text(s.to_string()))
343                .collect();
344            map.insert(
345                renewal_params::HEADER_PARAMS,
346                CborValue::Array(params_array),
347            );
348        }
349
350        map
351    }
352
353    /// Creates a redirect renewal claim
354    pub fn redirect_renewal(
355        exp_add: i64,
356        deadline: Option<i64>,
357        status_code: Option<i64>,
358    ) -> BTreeMap<i32, CborValue> {
359        let mut map = BTreeMap::new();
360        map.insert(
361            renewal_params::TYPE,
362            CborValue::Integer(renewal_types::REDIRECT as i64),
363        );
364        map.insert(renewal_params::EXPADD, CborValue::Integer(exp_add));
365
366        if let Some(deadline_value) = deadline {
367            map.insert(renewal_params::DEADLINE, CborValue::Integer(deadline_value));
368        }
369
370        if let Some(code) = status_code {
371            map.insert(renewal_params::STATUS_CODE, CborValue::Integer(code));
372        }
373
374        map
375    }
376}
377
378/// Helper functions for creating CATM (Common Access Token Methods) claims
379pub mod catm {
380    use super::*;
381
382    /// Creates a CATM claim with the specified HTTP methods
383    pub fn create(methods: Vec<&str>) -> Vec<CborValue> {
384        methods
385            .into_iter()
386            .map(|s| CborValue::Text(s.to_string()))
387            .collect()
388    }
389}
390
391/// Helper functions for creating CATREPLAY claims
392pub mod catreplay {
393    use super::*;
394    use crate::constants::replay_values;
395
396    /// Creates a CATREPLAY claim with the specified value
397    pub fn create(value: i32) -> CborValue {
398        CborValue::Integer(value as i64)
399    }
400
401    /// Creates a CATREPLAY claim with "permitted" value
402    pub fn permitted() -> CborValue {
403        CborValue::Integer(replay_values::PERMITTED as i64)
404    }
405
406    /// Creates a CATREPLAY claim with "prohibited" value
407    pub fn prohibited() -> CborValue {
408        CborValue::Integer(replay_values::PROHIBITED as i64)
409    }
410
411    /// Creates a CATREPLAY claim with "reuse detection" value
412    pub fn reuse_detection() -> CborValue {
413        CborValue::Integer(replay_values::REUSE_DETECTION as i64)
414    }
415}
416
417/// Helper functions for creating CATV (Common Access Token Version) claims
418pub mod catv {
419    use super::*;
420
421    /// Creates a CATV claim with version 1
422    pub fn create() -> CborValue {
423        CborValue::Integer(1)
424    }
425
426    /// Creates a CATV claim with a specific version number
427    pub fn with_version(version: i64) -> CborValue {
428        CborValue::Integer(version)
429    }
430}
431
432/// Helper functions for creating CATPOR (Common Access Token Probability of Rejection) claims
433///
434/// CATPOR specifies the probability that a token might be rejected, used for probabilistic
435/// rate limiting or load shedding.
436pub mod catpor {
437    use super::*;
438
439    /// Creates a CATPOR claim with a probability value (0.0 to 1.0)
440    ///
441    /// The probability is encoded as an integer representing the percentage (0-100).
442    ///
443    /// # Example
444    ///
445    /// ```
446    /// use common_access_token::cat_claims::catpor;
447    ///
448    /// // 25% probability of rejection
449    /// let catpor_claim = catpor::create(25);
450    /// ```
451    pub fn create(probability_percent: i64) -> CborValue {
452        CborValue::Integer(probability_percent)
453    }
454}
455
456/// Helper functions for creating CATNIP (Common Access Token Network IP) claims
457///
458/// CATNIP restricts the IP addresses from which the token can be used.
459pub mod catnip {
460    use super::*;
461
462    /// Creates a CATNIP claim with a list of allowed IP addresses or ranges
463    ///
464    /// # Example
465    ///
466    /// ```
467    /// use common_access_token::cat_claims::catnip;
468    ///
469    /// // Allow specific IP addresses
470    /// let catnip_claim = catnip::create(vec!["192.168.1.100", "10.0.0.0/8"]);
471    /// ```
472    pub fn create(ip_addresses: Vec<&str>) -> Vec<CborValue> {
473        ip_addresses
474            .into_iter()
475            .map(|ip| CborValue::Text(ip.to_string()))
476            .collect()
477    }
478
479    /// Creates a CATNIP claim with a single IP address
480    pub fn single(ip_address: &str) -> Vec<CborValue> {
481        vec![CborValue::Text(ip_address.to_string())]
482    }
483}
484
485/// Helper functions for creating CATALPN (Common Access Token ALPN) claims
486///
487/// CATALPN restricts the TLS Application-Layer Protocol Negotiation values.
488pub mod catalpn {
489    use super::*;
490
491    /// Creates a CATALPN claim with a list of allowed ALPN protocols
492    ///
493    /// # Example
494    ///
495    /// ```
496    /// use common_access_token::cat_claims::catalpn;
497    ///
498    /// // Allow HTTP/2 and HTTP/1.1
499    /// let catalpn_claim = catalpn::create(vec!["h2", "http/1.1"]);
500    /// ```
501    pub fn create(protocols: Vec<&str>) -> Vec<CborValue> {
502        protocols
503            .into_iter()
504            .map(|proto| CborValue::Text(proto.to_string()))
505            .collect()
506    }
507
508    /// Creates a CATALPN claim for HTTP/2 only
509    pub fn http2_only() -> Vec<CborValue> {
510        vec![CborValue::Text("h2".to_string())]
511    }
512
513    /// Creates a CATALPN claim for HTTP/1.1 only
514    pub fn http1_only() -> Vec<CborValue> {
515        vec![CborValue::Text("http/1.1".to_string())]
516    }
517}
518
519/// Helper functions for creating CATH (Common Access Token Header) claims
520///
521/// CATH specifies HTTP header requirements or restrictions.
522pub mod cath {
523    use super::*;
524
525    /// Creates a CATH claim with header name-value pairs
526    ///
527    /// # Example
528    ///
529    /// ```
530    /// use common_access_token::cat_claims::cath;
531    /// use std::collections::BTreeMap;
532    ///
533    /// let mut headers = BTreeMap::new();
534    /// headers.insert("X-Custom-Header", "required-value");
535    /// headers.insert("User-Agent", "MyApp/1.0");
536    /// let cath_claim = cath::create(headers);
537    /// ```
538    pub fn create(headers: BTreeMap<&str, &str>) -> CborValue {
539        let mut map = BTreeMap::new();
540        for (i, (key, value)) in headers.iter().enumerate() {
541            let mut header_map = BTreeMap::new();
542            header_map.insert(0, CborValue::Text(key.to_string()));
543            header_map.insert(1, CborValue::Text(value.to_string()));
544            map.insert(i as i32, CborValue::Map(header_map));
545        }
546        CborValue::Map(map)
547    }
548}
549
550/// Helper functions for creating CATGEOISO3166 (Common Access Token Geographic ISO3166) claims
551///
552/// CATGEOISO3166 restricts token usage to specific countries or regions.
553pub mod catgeoiso3166 {
554    use super::*;
555
556    /// Creates a CATGEOISO3166 claim with ISO 3166 country codes
557    ///
558    /// # Example
559    ///
560    /// ```
561    /// use common_access_token::cat_claims::catgeoiso3166;
562    ///
563    /// // Allow usage in US and Canada
564    /// let catgeoiso3166_claim = catgeoiso3166::create(vec!["US", "CA"]);
565    /// ```
566    pub fn create(country_codes: Vec<&str>) -> Vec<CborValue> {
567        country_codes
568            .into_iter()
569            .map(|code| CborValue::Text(code.to_string()))
570            .collect()
571    }
572}
573
574/// Helper functions for creating CATGEOCOORD (Common Access Token Geographic Coordinate) claims
575///
576/// CATGEOCOORD restricts token usage based on geographic coordinates.
577pub mod catgeocoord {
578    use super::*;
579
580    /// Creates a CATGEOCOORD claim with latitude and longitude
581    ///
582    /// # Example
583    ///
584    /// ```
585    /// use common_access_token::cat_claims::catgeocoord;
586    ///
587    /// // Center of New York City
588    /// let catgeocoord_claim = catgeocoord::create(40.7128, -74.0060);
589    /// ```
590    pub fn create(latitude: f64, longitude: f64) -> CborValue {
591        let mut map = BTreeMap::new();
592        // Using i64 representation of coordinates (multiply by 1e7 for precision)
593        map.insert(0, CborValue::Integer((latitude * 10_000_000.0) as i64));
594        map.insert(1, CborValue::Integer((longitude * 10_000_000.0) as i64));
595        CborValue::Map(map)
596    }
597
598    /// Creates a CATGEOCOORD claim with latitude, longitude, and radius in meters
599    pub fn with_radius(latitude: f64, longitude: f64, radius_meters: i64) -> CborValue {
600        let mut map = BTreeMap::new();
601        map.insert(0, CborValue::Integer((latitude * 10_000_000.0) as i64));
602        map.insert(1, CborValue::Integer((longitude * 10_000_000.0) as i64));
603        map.insert(2, CborValue::Integer(radius_meters));
604        CborValue::Map(map)
605    }
606}
607
608/// Helper functions for creating CATGEOALT (Common Access Token Geographic Altitude) claims
609///
610/// CATGEOALT restricts token usage based on altitude.
611pub mod catgeoalt {
612    use super::*;
613
614    /// Creates a CATGEOALT claim with altitude in meters
615    ///
616    /// # Example
617    ///
618    /// ```
619    /// use common_access_token::cat_claims::catgeoalt;
620    ///
621    /// // Sea level
622    /// let catgeoalt_claim = catgeoalt::create(0);
623    /// ```
624    pub fn create(altitude_meters: i64) -> CborValue {
625        CborValue::Integer(altitude_meters)
626    }
627
628    /// Creates a CATGEOALT claim with altitude range (min and max in meters)
629    pub fn range(min_meters: i64, max_meters: i64) -> CborValue {
630        let mut map = BTreeMap::new();
631        map.insert(0, CborValue::Integer(min_meters));
632        map.insert(1, CborValue::Integer(max_meters));
633        CborValue::Map(map)
634    }
635}
636
637/// Helper functions for creating CATTPK (Common Access Token TLS Public Key) claims
638///
639/// CATTPK pins the token to a specific TLS public key or certificate.
640pub mod cattpk {
641    use super::*;
642
643    /// Creates a CATTPK claim with a public key hash
644    ///
645    /// # Example
646    ///
647    /// ```
648    /// use common_access_token::cat_claims::cattpk;
649    ///
650    /// // SHA-256 hash of the public key
651    /// let key_hash = vec![0x01, 0x02, 0x03]; // truncated for example
652    /// let cattpk_claim = cattpk::create(key_hash);
653    /// ```
654    pub fn create(public_key_hash: Vec<u8>) -> CborValue {
655        CborValue::Bytes(public_key_hash)
656    }
657
658    /// Creates a CATTPK claim with multiple public key hashes
659    pub fn multiple(public_key_hashes: Vec<Vec<u8>>) -> Vec<CborValue> {
660        public_key_hashes
661            .into_iter()
662            .map(CborValue::Bytes)
663            .collect()
664    }
665}
666
667/// Helper functions for creating CATDPOP (Common Access Token DPoP Settings) claims
668///
669/// CATDPOP provides settings for Demonstrating Proof-of-Possession.
670pub mod catdpop {
671    use super::*;
672
673    /// Creates a CATDPOP claim with DPoP configuration
674    ///
675    /// # Example
676    ///
677    /// ```
678    /// use common_access_token::cat_claims::catdpop;
679    /// use std::collections::BTreeMap;
680    ///
681    /// let mut dpop_config = BTreeMap::new();
682    /// dpop_config.insert(0, common_access_token::CborValue::Integer(1)); // version
683    /// dpop_config.insert(1, common_access_token::CborValue::Text("RS256".to_string())); // algorithm
684    /// let catdpop_claim = catdpop::create(dpop_config);
685    /// ```
686    pub fn create(config: BTreeMap<i32, CborValue>) -> CborValue {
687        CborValue::Map(config)
688    }
689
690    /// Creates a basic CATDPOP claim requiring DPoP
691    pub fn required() -> CborValue {
692        let mut map = BTreeMap::new();
693        map.insert(0, CborValue::Integer(1)); // required
694        CborValue::Map(map)
695    }
696}
697
698/// Helper functions for creating CATIF (Common Access Token If) claims
699///
700/// CATIF provides conditional logic for token handling.
701pub mod catif {
702    use super::*;
703
704    /// Creates a CATIF claim with conditional expressions
705    ///
706    /// # Example
707    ///
708    /// ```
709    /// use common_access_token::cat_claims::catif;
710    /// use std::collections::BTreeMap;
711    ///
712    /// let mut condition = BTreeMap::new();
713    /// condition.insert(0, common_access_token::CborValue::Text("status".to_string()));
714    /// condition.insert(1, common_access_token::CborValue::Text("eq".to_string()));
715    /// condition.insert(2, common_access_token::CborValue::Integer(200));
716    /// let catif_claim = catif::create(condition);
717    /// ```
718    pub fn create(condition: BTreeMap<i32, CborValue>) -> CborValue {
719        CborValue::Map(condition)
720    }
721}
722
723/// Helper functions for creating CATIFDATA (Common Access Token If Data) claims
724///
725/// CATIFDATA provides data for conditional evaluation in CATIF.
726pub mod catifdata {
727    use super::*;
728
729    /// Creates a CATIFDATA claim with data values
730    ///
731    /// # Example
732    ///
733    /// ```
734    /// use common_access_token::cat_claims::catifdata;
735    /// use std::collections::BTreeMap;
736    ///
737    /// let mut data = BTreeMap::new();
738    /// data.insert(0, common_access_token::CborValue::Text("user_role".to_string()));
739    /// data.insert(1, common_access_token::CborValue::Text("admin".to_string()));
740    /// let catifdata_claim = catifdata::create(data);
741    /// ```
742    pub fn create(data: BTreeMap<i32, CborValue>) -> CborValue {
743        CborValue::Map(data)
744    }
745}