pdk_jwt_lib/validator/
es_validator.rs1use std::time::{SystemTime, UNIX_EPOCH};
11
12use elliptic_curve::pkcs8::LineEnding::CR;
13use elliptic_curve::pkcs8::{AssociatedOid, EncodePublicKey};
14use elliptic_curve::sec1::{FromEncodedPoint, ModulusSize, ToEncodedPoint};
15use elliptic_curve::{CurveArithmetic, JwkParameters, PublicKey};
16use jwt_simple::prelude::{
17 Duration, ECDSAP256PublicKeyLike, ECDSAP384PublicKeyLike, ES256PublicKey, ES384PublicKey,
18 VerificationOptions,
19};
20
21use super::signature_validator::SignatureValidation;
22use crate::error::jwt_error::JWTError;
23use crate::model::claims::{CustomClaims, JWTClaims, TryFromTrustedJWTSimpleClaims};
24use crate::model::signing_algorithm::SigningKeyLength;
25use crate::model::untrusted_token::untrusted_jwt::UntrustedJWT;
26use crate::parser::es_pk_parser::parse_es_pk;
27
28pub struct EsSignatureValidator<C: CurveArithmetic> {
31 key_length: SigningKeyLength,
32 key: PublicKey<C>,
33}
34
35impl<C> EsSignatureValidator<C>
36where
37 C: CurveArithmetic + JwkParameters + AssociatedOid,
38 <C as CurveArithmetic>::AffinePoint: FromEncodedPoint<C>,
39 <C as elliptic_curve::Curve>::FieldBytesSize: ModulusSize,
40 <C as CurveArithmetic>::AffinePoint: ToEncodedPoint<C>,
41{
42 pub fn new(key_length: SigningKeyLength, key: String) -> Result<Self, JWTError> {
43 let key = parse_es_pk(key)?;
44 Ok(Self { key_length, key })
45 }
46}
47
48impl<C> SignatureValidation for EsSignatureValidator<C>
49where
50 C: CurveArithmetic + JwkParameters + AssociatedOid,
51 <C as CurveArithmetic>::AffinePoint: FromEncodedPoint<C>,
52 <C as elliptic_curve::Curve>::FieldBytesSize: ModulusSize,
53 <C as CurveArithmetic>::AffinePoint: ToEncodedPoint<C>,
54{
55 fn validate(&self, token: String) -> Result<JWTClaims, JWTError> {
56 UntrustedJWT::new(token.as_str())
57 .and_then(|token| {
58 let str_key = self.key.to_public_key_pem(CR)?;
59 as_es_algorithm(&self.key_length, str_key.as_str())?
60 .verify_token(token.value().as_str())
61 })
62 .and_then(|claims| JWTClaims::try_from_trusted_jwt_simple_claims(claims, token))
63 }
64}
65
66fn full_tolerance() -> core::time::Duration {
67 core::time::Duration::from_secs(Duration::from_days(365 * 50).as_secs())
68}
69
70enum EsPublicKey {
71 ES256 { pk: ES256PublicKey },
72 ES384 { pk: ES384PublicKey },
73}
74
75impl EsPublicKey {
76 fn verify_token(
77 &self,
78 token: &str,
79 ) -> Result<jwt_simple::claims::JWTClaims<CustomClaims>, JWTError> {
80 let now = SystemTime::now()
81 .duration_since(UNIX_EPOCH)
82 .unwrap_or_else(|_| full_tolerance());
83
84 let options = VerificationOptions {
85 accept_future: true,
86 time_tolerance: Some(Duration::from(now)),
87 ..Default::default()
88 };
89
90 match self {
91 EsPublicKey::ES256 { pk } => pk
92 .verify_token::<CustomClaims>(token, Some(options))
93 .map_err(JWTError::from),
94 EsPublicKey::ES384 { pk } => pk
95 .verify_token::<CustomClaims>(token, Some(options))
96 .map_err(JWTError::from),
97 }
98 }
99}
100
101fn as_es_algorithm(key_length: &SigningKeyLength, key: &str) -> Result<EsPublicKey, JWTError> {
102 match (key_length, key) {
103 (SigningKeyLength::Len256, key) => Ok(EsPublicKey::ES256 {
104 pk: ES256PublicKey::from_pem(key)?,
105 }),
106 (SigningKeyLength::Len384, key) => Ok(EsPublicKey::ES384 {
107 pk: ES384PublicKey::from_pem(key)?,
108 }),
109 _ => Err(JWTError::InvalidKeyLength(format!(
110 "Invalid configuration: Key length {key_length:?} is not valid for algorithm ES"
111 ))),
112 }
113}
114
115impl From<elliptic_curve::pkcs8::spki::Error> for crate::error::jwt_error::JWTError {
116 fn from(e: elliptic_curve::pkcs8::spki::Error) -> Self {
117 JWTError::EsPublicKeyParseFailed(format!("ES Public key parsing error: {e}"))
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::EsSignatureValidator;
124 use crate::model::signing_algorithm::SigningKeyLength;
125 use p256::NistP256;
126 use p384::NistP384;
127
128 const ES_PUBLIC_KEY_PEM: &str = "-----BEGIN PUBLIC KEY-----
129MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERqVXn+o+6zEOpWEsGw5CsB+wd8zO
130jxu0uASGpiGP+wYfcc1unyMxcStbDzUjRuObY8DalaCJ9/J6UrkQkZBtZw==
131-----END PUBLIC KEY-----";
132
133 const ES_384_PUBLIC_KEY_PEM: &str = "-----BEGIN PUBLIC KEY-----
134MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEjjUFluy6cFrvj/UQwTJoEhPLEJSrKkx0
135Rqxc0HEHdFuj0dpj977K9LoYRvZopFk8roS1DW3wghytCEfnW6AWNiesqa4S4iux
136oomerb1S3+mXzX4p5459w9axcam9qgjo
137-----END PUBLIC KEY-----";
138
139 fn es256_validator() -> EsSignatureValidator<NistP256> {
140 EsSignatureValidator::new(SigningKeyLength::Len256, String::from(ES_PUBLIC_KEY_PEM))
141 .unwrap()
142 }
143
144 fn es384_validator() -> EsSignatureValidator<NistP384> {
145 EsSignatureValidator::new(
146 SigningKeyLength::Len384,
147 String::from(ES_384_PUBLIC_KEY_PEM),
148 )
149 .unwrap()
150 }
151
152 mod es_validator_256 {
153 use crate::error::jwt_error::JWTErrorEnumKind;
154 use crate::validator::es_validator::tests::es256_validator;
155 use crate::validator::es_validator::SignatureValidation;
156 use crate::validator::signature_validator::tests::assert_error_kind;
157 use test_case::test_case;
158
159 extern crate test_case;
160
161 #[test]
162 fn validation_ok_and_jwt_parsed() {
163 let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJleHAiOjkyMDA5ODUyNH0.ba5H-gFMcWnu-02y_5ITZVX4FSw2d9zE6BJJCWulWOMMuXaSX4-lBVPCjMpSPBE6fNlnWg4Po6bUf0gRdZCAlg";
164
165 let validation = es256_validator().validate(token.to_string());
166
167 assert!(validation.is_ok());
168
169 let jwt_claims = validation.unwrap();
170
171 assert_eq!(jwt_claims.get_header("alg").unwrap(), "ES256");
173 assert_eq!(
174 jwt_claims.expiration().unwrap().to_string(),
175 "1999-02-27 06:55:24 UTC"
176 );
177 }
178
179 #[test]
180 fn validation_fails_when_token_not_sent() {
181 let token = "";
182
183 let validation = es256_validator().validate(token.to_string());
184
185 assert_error_kind(&validation, JWTErrorEnumKind::ValidationFailed);
186 }
187
188 #[test]
189 fn unparseable_token_is_rejected() {
190 let token = "WhatAmI?AnInvalidToken!";
191
192 let validation = es256_validator().validate(token.to_string());
193
194 assert_error_kind(&validation, JWTErrorEnumKind::ValidationFailed);
195 }
196
197 #[test]
198 fn validation_fails_on_invalid_signature() {
199 let token = "eyJraWQiOiI5OWNiY2EzYS1kZmM4LTQ3NjgtODQ4MC0yZmIwZWVjZTkyZjEiLCJhbGciOiJFUzI1NiJ9.ew0KICAic3ViIjogIjEyMzQ1Njc4OTAiLA0KICAibmFtZSI6ICJBbmlzaCBOYXRoIiwNCiAgImlhdCI6IDE1MTYyMzkwMjINCn0.OS4wEFUvkfHG_wOPFBDVq04F7NDUvvwFmTR147hoP6IjqmwkDBeslsN_5YMcqGR8wztvQYmPi785xJshja9uVA";
200
201 let validation = es256_validator().validate(token.to_string());
202
203 assert_error_kind(&validation, JWTErrorEnumKind::ValidationFailed);
204 }
205
206 #[test]
207 fn validation_fails_on_missing_signature() {
208 let token = "eyJraWQiOiI5NDE2YWY5ZS1jMTZlLTRjM2UtYmNkNy1kODFmMTdkZjBhN2YiLCJhbGciOiJFUzI1NiJ9.ew0KfQ.X_HB6PXUBcMlFjPAZYFRpgJLIzZO6ADcrqnSS4Sq2nVdcQtjkknuwxptjyFpNU5iP7PAFjYwRSMubgh4cQHNqA";
209
210 let validation = es256_validator().validate(token.to_string());
211
212 assert_error_kind(&validation, JWTErrorEnumKind::ValidationFailed);
213 }
214
215 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.e30.zWty50iXfn_2RtgdvqJ-A7xhkqSeO2UtAa_W9-RASE7ofEkGArOffQUOtQv76v1tQXDUqlQFf9FOms4FKPaQKA"; "verifyValidToken 256")]
216 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJleHAiOjkyMDA5ODUyNH0.ba5H-gFMcWnu-02y_5ITZVX4FSw2d9zE6BJJCWulWOMMuXaSX4-lBVPCjMpSPBE6fNlnWg4Po6bUf0gRdZCAlg"; "exceptionNotThrownOnExpiredTokenWithNoClaimValidation 256")]
217 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.e30.zWty50iXfn_2RtgdvqJ-A7xhkqSeO2UtAa_W9-RASE7ofEkGArOffQUOtQv76v1tQXDUqlQFf9FOms4FKPaQKA"; "exceptionNotThrownOnMissingClaim 256")]
218 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJleHAiOjMyODAzOTQwOTh9.0rFDoK4mv20SBw2rhNIXcNb4gCIElIzXm9pZYyi0XJ3wvFP9-NmRtOBhBOhEiF4S6tpw2u1Mjvv05yQbqsWfRA"; "verifyNotExpiredToken 256")]
219 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJleHAiOjkyMDA5ODUyNH0.ba5H-gFMcWnu-02y_5ITZVX4FSw2d9zE6BJJCWulWOMMuXaSX4-lBVPCjMpSPBE6fNlnWg4Po6bUf0gRdZCAlg"; "exceptionNotThrownOnExpiredToken 256")]
220 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJuYmYiOjgyMDA5ODUyNH0.jpshS_OqCYjhHlji9vLFlQ4gRFeHXOwx4TzDGpz3lKzgIqGpYgXvuspVrDAZNsbt_WUq4XkynJj7I1SKXdljUg"; "verifyTokenWithNbf 256")]
221 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJuYmYiOjMyODAzOTQwOTh9.BFmaYwAqljy5T7CWwndf_5hwJljasmCNwyM8paOqtBULbyZBrdpT9ZK1co2lD60IdFvAivmEuWEZqpldK3CuJg"; "exceptionNotThrownNotYetActiveToken 256")]
222 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJmb28ifQ.1urtAG-oabmrWjH3OVxu--e0UPa5dpxXtZ7CFJGQxFG0IGzPM4LLyxBenWs-9Ue07dPXISuBa77yMTzmuqcLBQ"; "verifyTokenWithAud 256")]
223 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOlsiZXRjIiwiZm9vIiwiYmxhaCJdfQ.wEQIdgpzCMK4O3f9obSVit7-IJTOvJm8fWY9j0w-9vJxyxU2zCto7oCx5B2Z8OmWS9oD4bvc1KlEpd_-i7Vi2A"; "verifyTokenWithAudArray 256")]
224 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOlsiZXRjIiwiZm9vIGJhciIsImJsYWgiXX0.rtdfw_0B0OVyzRg86IfvXpymK4ukg5vVLxsCKtRj9soxk_4X-xSyDgv9sN_cTfTPOq1upsotUFBoWMhIEUve2Q"; "verifyTokenWithAudiencesWithSpaces 256")]
225 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOlsiZXRjIiwiRm9vIiwiYmxhaCJdfQ.Wk6KIMh858nuaa2caoRNiUahZl9KlJbAZ5AgtSUMH-96hJs7naNfzeux-cZ-tuil6ePTLvjwsranIAvDWznamw"; "verifyTokenWithAudiencesCaseSensitive 256")]
226 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOlsiZXRjIiwiYmxhaCJdfQ.SFdcVoIGlJTDAkao6QfjOQEDPq4lAzVjcWQOBXUZ3_EqIWUCJ6XEohhghuux8QbSDmhj36mVimrBbQ4IcyvYJw"; "exceptionNotThrownWhenInvalidAudToken 256")]
227 #[test_case("eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJmb28iLCJuYmYiOjgyMDA5ODUyNCwibmFtZSI6IkpvaG4gRG9lIiwic2NvcGVzIjpbInJlYWQiLCJ3cml0ZSJdLCJleHAiOjMyODAzOTQwOTh9.xfaGYUA1xGgYQjdiWFT8JT8AHdZochXx8VkvP1dnUgV-SmdefElAy3JaXKfpnVFM-7DvcnEeUYycQCNL3qS9lA"; "checkAllValidations 256")]
228 fn verify_valid_token_256(token: &str) {
229 let validation = es256_validator().validate(token.to_string());
230
231 assert!(validation.is_ok());
232 }
233 }
234
235 mod es_validator_384 {
236 use crate::error::jwt_error::JWTErrorEnumKind;
237 use crate::validator::es_validator::tests::es384_validator;
238 use crate::validator::es_validator::SignatureValidation;
239 use crate::validator::signature_validator::tests::assert_error_kind;
240 use test_case::test_case;
241
242 extern crate test_case;
243
244 #[test]
245 fn validation_ok() {
246 let token = "eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNjU4NDMwNjg2LCJleHAiOjE2NTg5NDg2MzF9.Bm6E2fuWizA8WObF6tWl80Gyak79H6FaD4Fxn9d0Gr-IGih5PvntcXHHl18p1DYFLsrt9xPfIAAaWsIk6VfrtCNb65Y2nzqDJUCNcYtFBvxY8NPY2dRLC3Gl5HAqVvex";
247
248 let validation = es384_validator().validate(token.to_string());
249
250 assert!(validation.is_ok());
251 }
252
253 #[test]
254 fn validation_fails_when_token_not_sent() {
255 let token = "eyJraWQiOiI5NDE2YWY5ZS1jMTZlLTRjM2UtYmNkNy1kODFmMTdkZjBhN2YiLCJhbGciOiJFUzI1NiJ9.ew0KfQ.X_HB6PXUBcMlFjPAZYFRpgJLIzZO6ADcrqnSS4Sq2nVdcQtjkknuwxptjyFpNU5iP7PAFjYwRSMubgh4cQHNqA";
256
257 let validation = es384_validator().validate(token.to_string());
258
259 assert_error_kind(&validation, JWTErrorEnumKind::ValidationFailed);
260 }
261
262 #[test]
263 fn unparseable_token_is_rejected() {
264 let token = "WhatAmI?AnInvalidToken!";
265
266 let validation = es384_validator().validate(token.to_string());
267
268 assert_error_kind(&validation, JWTErrorEnumKind::ValidationFailed);
269 }
270
271 #[test]
272 fn validation_fails_on_invalid_signature() {
273 let token = "eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFuaXNoIE5hdGgiLCJpYXQiOjE1MTYyMzkwMjJ9.6adcW-2ww22MC3n41o5b6wULVolXno4md0glQR1U9hfIpbyyWQS2U-947x4mnc6bx-pxKO9SjnLtv7rsvOjvP300K5WayPIISQ0lc7CDkKH2s3oT1Bw5gHVtKfYT5Gjv";
274
275 let validation = es384_validator().validate(token.to_string());
276
277 assert_error_kind(&validation, JWTErrorEnumKind::ValidationFailed);
278 }
279
280 #[test]
281 fn validation_fails_on_missing_signature() {
282 let token = "";
283
284 let validation = es384_validator().validate(token.to_string());
285
286 assert_error_kind(&validation, JWTErrorEnumKind::ValidationFailed);
287 }
288
289 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.e30.LLv51B6Y7ksfwFNLeMuF_nWNVHjvZwU75MC6uVJCFqYag7RogTHuEMIc5PsE42fwAlsKaY8pWQbzLeMkl7-vC0fkMvj7YDIowWYE15gfHigzbrelwpgFZ8k6SzdIKZJ2"; "verifyValidToken 384")]
290 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJleHAiOjkyMDA5ODUyNH0._IIq-sOy4JExOTJphYrxcogGc7dEc80xNLqz0FmY_6FAgH_W1E6ihitVnMwAg1WUKJZAPIuLCZtdCiWi69aH5Uz_YGKPZjppOqETgHuoQ8C89z2gQ313LgoyBv-ebvpB"; "exceptionNotThrownOnExpiredTokenWithNoClaimValidation 384")]
291 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.e30.6BJi3OGsiXOyRwUfu663r9SL0NzuYkdOQ_MS46WfGSWBXHc8WS_VpKlt4wZXaZMOQKndDCPdKbvXSLnrJ0pNWGiwQ7IufviWxhXkMJL6jll9Jwf1-y8EXQt1NiY8aYvR"; "exceptionNotThrownOnMissingClaim 384")]
292 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJleHAiOjMyODAzOTQwOTh9.LxipZW5nkk-T-2mRxLzmEE44lKy4cc3eHLWI3LfDPHFO_qhZIqaGxhS7SwBk6HNCiJ61EOHq-YjehMa1xxaKupfa6n7MlVm9EqHhPXyONqfiH3BchxhqC1KbDv9TrKyz"; "verifyNotExpiredToken 384")]
293 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJleHAiOjkyMDA5ODUyNC4zMjF9.Xyn-wcsh_SCoBFJZkQUC5jeJYSuXpF1k7UbgQN0jwZJSBCCkxOYjzevuCXtZJsnySmYkyuP-7K6YPtLpiS7Nmqz--1AN6S6u4l3TO-20PjybFhEckZEGVYf98esmcwHm"; "exceptionNotThrownOnExpiredToken 384")]
294 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJuYmYiOjgyMDA5ODUyNC40MzN9.Db2CqHjYHIvB_pb2_p3GfI57KRHGa_MYJ3dF5Or4vM4JQG5E756Lm21_dSqYDJnA6roan7z92uuoqpFRRNmdHjTz8zgP_QBcdSQhUsogA3YlE27o-oveGsjDOWQG_88l"; "verifyTokenWithNbf 384")]
295 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJuYmYiOjMyODAzOTQwOTguMzQyfQ.H3DWycc7O1QY4_V8alWXQf9cuxYmRPkKdmaiQ8yTVj5LaOTDxoVeFYusQWC8NQ0ZbYrEqZNHLcZlTQZ55fsaYPXrRgLaeqCQ_BGeMJZqj8btzoZ8AKGUtWYbUhCD6UfL"; "exceptionNotThrownNotYetActiveToken 384")]
296 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJmb28ifQ.pdejdj6fkVgxQLzW_hj40tbk2Nc2WFcfrzdtIT2ZKbd9UA24nO_eYjz411eR8wN0uYMPlgkGXeMFRCw-TMmmTvhhqLy-3tgFfdMtfD6HkxVhFRSK1q7ZUWOfumNmspgR"; "verifyTokenWithAud 384")]
297 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiZXRjIiwiZm9vIiwiYmxhaCJdfQ.KhcqpcQdiOPy_fiVjDqmETW1uxgKoVlQqF4aMvterke0i6GdD0d5Bst5_wxz4l4Q54Ybw6uLHRwXT7Afc9RTDPBQqRLf2CgidRu72NukcXufYpJyPsyelneETSAC855N"; "verifyTokenWithAudArray 384")]
298 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiZXRjIiwiZm9vIGJhciIsImJsYWgiXX0.v-yysmA64_SJ0w9eZPL3NNQFCpJYweFvy7LJP84N_6NDA1RjAicAi7Gt6DIAdG-cFG0Jn8NJM4DdwRBJUycGrOILCOgmio-bh63S-FwBLk3ExAJzrAr_yiMWLEvekgR6"; "verifyTokenWithAudiencesWithSpaces 384")]
299 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiZXRjIiwiRm9vIiwiYmxhaCJdfQ.irwNz94eGFFXblZSxC4OGAs3pzR07b1VAaEGfzu_2QcTAHqMSLw1c7HmeBDczwNY89X1smiVhFx6R1COJ8CA9c1h9vrYe1ED_LfElVfvTSpYHNcPWgBLFsvQI7k98xL4"; "verifyTokenWithAudiencesCaseSensitive 384")]
300 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiZXRjIiwiYmxhaCJdfQ.9C3CuglaBOiKoJQycEjVg2NOap2RbQVhSdqJk6V3tC3mK3OzxFouPuzb7ZLNlJh73UbD-gHXZxieFTNAc60dcYVt-tuUMYA9Atp-FZTeoZ973a-KI_DHb9BLiLo0hgYi"; "exceptionNotThrownWhenInvalidAudToken 384")]
301 #[test_case("eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJmb28iLCJuYmYiOjgyMDA5ODUyNCwibmFtZSI6IkpvaG4gRG9lIiwic2NvcGVzIjpbInJlYWQiLCJ3cml0ZSJdLCJleHAiOjMyODAzOTQwOTh9.4_AS9rscqomVqrAuF3JuV9WT-dahxNik3U5ou-nLmYK8Is-7ddkP1tLfQm5ufcRUXrN9HbyXdNy9Afr8TP0Vd72v45HKEZancXaghzlhmGGROesshVwBRltC1XLYEsIE"; "checkAllValidations 384")]
302 fn verify_valid_token_384(token: &str) {
303 let validation = es384_validator().validate(token.to_string());
304
305 assert!(validation.is_ok());
306 }
307 }
308}