1pub mod v0;
17pub mod v1;
18
19use std::time::SystemTime;
20
21use scion_sdk_token_validator::validator::Token;
22use serde::{Deserialize, Serialize};
23
24#[derive(Debug, Clone, Serialize)]
31#[serde(untagged)]
32pub enum AnyClaims {
33 V1(v1::SnapTokenClaims),
35 V0(v0::SnapTokenClaims),
37}
38
39impl<'de> Deserialize<'de> for AnyClaims {
40 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
41 where
42 D: serde::Deserializer<'de>,
43 {
44 let value = serde_json::Value::deserialize(deserializer)?;
45
46 if let Some(ver) = value.get("ver") {
49 match ver.as_u64() {
50 Some(1) => {
51 let claims: v1::SnapTokenClaims =
52 serde_json::from_value(value).map_err(serde::de::Error::custom)?;
53 Ok(AnyClaims::V1(claims))
54 }
55 Some(n) => {
56 Err(serde::de::Error::custom(format!(
57 "unsupported SNAP token version: {}",
58 n
59 )))
60 }
61 None => {
62 Err(serde::de::Error::custom(
63 "invalid SNAP token: 'ver' claim must be a number",
64 ))
65 }
66 }
67 } else {
68 let claims: v0::SnapTokenClaims =
70 serde_json::from_value(value).map_err(serde::de::Error::custom)?;
71 Ok(AnyClaims::V0(claims))
72 }
73 }
74}
75impl AnyClaims {
76 pub fn pssid(&self) -> String {
78 match self {
79 AnyClaims::V1(c) => c.pssid.to_string(),
80 AnyClaims::V0(c) => c.pssid.to_string(),
81 }
82 }
83
84 pub fn jti(&self) -> String {
86 match self {
87 AnyClaims::V1(c) => c.jti.clone(),
88 AnyClaims::V0(c) => c.jti.clone(),
89 }
90 }
91}
92
93impl Token for AnyClaims {
94 fn id(&self) -> String {
95 match self {
96 Self::V1(c) => c.id(),
97 Self::V0(c) => c.id(),
98 }
99 }
100
101 fn exp_time(&self) -> SystemTime {
102 match self {
103 Self::V1(c) => c.exp_time(),
104 Self::V0(c) => c.exp_time(),
105 }
106 }
107
108 fn required_claims() -> Vec<&'static str> {
109 vec!["exp", "pssid"]
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use serde_json::json;
118
119 use super::*;
120
121 #[test]
122 fn test_any_claims_dispatch() {
123 let v0_json = json!({
125 "jti": "jti_v0",
126 "exp": 2000000000,
127 "pssid": "ef16640f-0fa9-4360-be74-dbeec7ab4f9a"
128 });
129 let c: AnyClaims = serde_json::from_value(v0_json).expect("should parse as V0");
130 assert!(matches!(c, AnyClaims::V0(_)));
131
132 let v1_json = json!({
134 "ver": 1,
135 "jti": "jti_v1",
136 "iss": "ssr",
137 "aud": "snap",
138 "exp": 2000000000,
139 "nbf": 1000,
140 "iat": 1000,
141 "pssid": "AAAAAAAAAAAAAAAAAAAAAAA",
142 "aa_acc_subject_id": "subj",
143 "aa_acc_allowed_dst": "[]"
144 });
145 let c: AnyClaims = serde_json::from_value(v1_json).expect("should parse as V1");
146 assert!(matches!(c, AnyClaims::V1(_)));
147
148 let v2_json = json!({
150 "ver": 2,
151 "exp": 2000000000
152 });
153 let err = serde_json::from_value::<AnyClaims>(v2_json).unwrap_err();
154 assert!(
155 err.to_string()
156 .contains("unsupported SNAP token version: 2")
157 );
158 }
159}