jwt/jwt.rs
1//! Sign, parse, and verify JSON Web Tokens (JWT).
2//!
3//! # Two-step verification flow
4//!
5//! [`parse_header`] and [`parse_and_verify`] are separate so that you can
6//! inspect the header, especially the `kid` field (Key ID), before choosing
7//! which key to verify with. This is essential when the key must be looked up dynamically.
8//!
9//! # `no_std` support
10//!
11//! Disable default features (`default-features = false`) and provide your own
12//! [`Clock`] implementation for time-based claim verification (optional).
13//!
14//! # Example
15//!
16//! ```
17//! use jwt::*;
18//! use crypto::curve25519::ed25519;
19//!
20//! fn main() -> Result<(), Error> {
21//! // 1. Generate an Ed25519 secret key.
22//! let secret_key = ed25519::SecretKey::generate();
23//!
24//! // 2. Build the header.
25//! let header = Header {
26//! typ: TokenType::JWT,
27//! alg: Algorithm::EdDSA,
28//! kid: Some("my-key-id".into()),
29//! cty: None,
30//! jku: None,
31//! x5u: None,
32//! x5c: None,
33//! x5t: None,
34//! x5t_s256: None,
35//! };
36//!
37//! // 3. Define the claims and sign.
38//! let claims = serde_json::json!({ "sub": "user123", "exp": 9999999999_u64 });
39//! let token = sign(&secret_key, &header, &claims)?;
40//!
41//! // 4. Extract the public key for verification.
42//! let public_key = secret_key.public_key();
43//!
44//! // 5. Parse only the header first (e.g., to read `kid` for key lookup).
45//! let parsed_header = parse_header(&token)?;
46//! assert_eq!(parsed_header.kid.as_deref(), Some("my-key-id"));
47//!
48//! // 6. Now verify and deserialize the claims.
49//! let opts = VerifyOptions {
50//! allowed_time_drift: core::time::Duration::from_secs(60),
51//! exp: true,
52//! nbf: false,
53//! aud: None,
54//! iss: None,
55//! clock: Some(&jwt::SYSTEM_CLOCK),
56//! };
57//! let claims: serde_json::Value =
58//! parse_and_verify(&public_key, &parsed_header, &token, &opts)?;
59//! assert_eq!(claims["sub"], "user123");
60//!
61//! Ok(())
62//! }
63//! ```
64//!
65//! # JSON Web Key (JWK) import and export
66//!
67//! Keys can be exported to and imported from JSON Web Keys (JWK) for publishing or later re-use.
68//! Every supported key type implements `From<&KeyType> for Jwk`, and the reverse conversion is
69//! available through `TryFrom<&Jwk>`. Use it when the key is only known at runtime, for example
70//! after fetching a JWKS document. P-256, P-384 and P-521 public keys are all supported.
71//!
72//! ```
73//! use jwt::*;
74//! use crypto::p256;
75//!
76//! fn main() -> Result<(), Error> {
77//! // Generate a P-256 key pair.
78//! let secret_key = p256::SecretKey::generate().map_err(|_| Error::InvalidKey)?;
79//! let public_key = secret_key.public_key();
80//!
81//! // Convert to a JWK (e.g. for publishing in a JWKS endpoint).
82//! let jwk = Jwk::from(&public_key);
83//! assert_eq!(jwk.algorithm, Algorithm::ES256);
84//!
85//! // Parse the JWK back into a key (e.g. from a JWKS response).
86//! let key = p256::PublicKey::try_from(&jwk)?;
87//!
88//! let header = Header { typ: TokenType::JWT, alg: Algorithm::ES256, ..Default::default() };
89//! let token = sign(&secret_key, &header, &serde_json::json!({"exp": 9999999999_u64, "nbf": 0_u64 }))?;
90//! let parsed_header = parse_header(&token)?;
91//! let _claims: serde_json::Value = parse_and_verify(&key, &parsed_header, &token, &VerifyOptions::default())?;
92//!
93//! Ok(())
94//! }
95//! ```
96//!
97//! When the key type is not known ahead of time (for example a JWKS document that may contain
98//! several kinds of keys), use the [`Key`] enum. It inspects the JWK's `kty` and `crv` and selects the
99//! matching concrete key, preferring the secret variant when both halves are present. [`Key`]
100//! implements both [`Signer`] and [`Verifier`], so it can be passed straight to [`sign`] or
101//! [`parse_and_verify`]:
102//!
103//! ```
104//! use jwt::*;
105//! use crypto::curve25519::ed25519;
106//!
107//! fn main() -> Result<(), Error> {
108//! let secret_key = ed25519::SecretKey::generate();
109//!
110//! // A JWKS entry whose key type is only known at runtime.
111//! let jwk = Jwk::from(&secret_key.public_key());
112//! let key = Key::try_from(&jwk)?;
113//! assert!(matches!(key, Key::Ed25519Public(_)));
114//!
115//! let header = Header { typ: TokenType::JWT, alg: Algorithm::EdDSA, ..Default::default() };
116//! let token = sign(&secret_key, &header, &serde_json::json!({"exp": 9999999999_u64, "nbf": 0_u64 }))?;
117//! let parsed_header = parse_header(&token)?;
118//! let _claims: serde_json::Value = parse_and_verify(&key, &parsed_header, &token, &VerifyOptions::default())?;
119//!
120//! Ok(())
121//! }
122//! ```
123//!
124//! When a JWK derived from a secret key is decoded, the secret variant is preferred, so the same
125//! [`Key`] can be used for signing:
126//!
127//! ```
128//! use jwt::*;
129//! use crypto::curve25519::ed25519;
130//!
131//! fn main() -> Result<(), Error> {
132//! let secret_key = ed25519::SecretKey::generate();
133//! let jwk = Jwk::from(&secret_key);
134//! let key = Key::try_from(&jwk)?;
135//! assert!(matches!(key, Key::Ed25519Secret(_)));
136//!
137//! let header = Header { typ: TokenType::JWT, alg: Algorithm::EdDSA, ..Default::default() };
138//! let token = sign(&key, &header, &serde_json::json!({"exp": 9999999999_u64, "nbf": 0_u64 }))?;
139//! let parsed_header = parse_header(&token)?;
140//! let _claims: serde_json::Value = parse_and_verify(&key, &parsed_header, &token, &VerifyOptions::default())?;
141//!
142//! Ok(())
143//! }
144//! ```
145
146#![cfg_attr(not(feature = "std"), no_std)]
147
148extern crate alloc;
149
150use alloc::{
151 string::{String, ToString},
152 vec::Vec,
153};
154use core::time::Duration;
155
156use serde::{Deserialize, Serialize, de::DeserializeOwned};
157use small_collections::SmallString;
158
159mod jwk;
160mod jwt_crypto;
161
162pub use jwk::*;
163pub use jwt_crypto::*;
164
165#[cfg(feature = "std")]
166pub static SYSTEM_CLOCK: SystemClock = SystemClock;
167
168#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
169pub struct Header {
170 /// The only valid value is "JWT"
171 /// https://tools.ietf.org/html/rfc7519#section-5.1
172 pub typ: TokenType,
173
174 /// ttps://tools.ietf.org/html/rfc7515#section-4.1.1
175 pub alg: Algorithm,
176
177 /// Content type
178 /// https://tools.ietf.org/html/rfc7519#section-5.2
179 #[serde(skip_serializing_if = "Option::is_none")]
180 pub cty: Option<SmallString<3>>,
181
182 /// JSON Key URL
183 /// https://tools.ietf.org/html/rfc7515#section-4.1.2
184 #[serde(skip_serializing_if = "Option::is_none")]
185 pub jku: Option<String>,
186
187 /// JSON Web Key
188 /// https://tools.ietf.org/html/rfc7515#section-4.1.3
189 // #[serde(skip_serializing_if = "Option::is_none")]
190 // pub jwk: Option<Jwk>,
191
192 /// Key ID
193 /// https://tools.ietf.org/html/rfc7515#section-4.1.4
194 #[serde(skip_serializing_if = "Option::is_none")]
195 pub kid: Option<SmallString<36>>, // 36 = UUID length
196
197 /// X.509 URL
198 /// https://tools.ietf.org/html/rfc7515#section-4.1.5
199 #[serde(skip_serializing_if = "Option::is_none")]
200 pub x5u: Option<String>,
201
202 /// X.509 certificate chain.
203 /// https://tools.ietf.org/html/rfc7515#section-4.1.6
204 #[serde(skip_serializing_if = "Option::is_none")]
205 pub x5c: Option<Vec<String>>,
206
207 /// X.509 SHA1 certificate Thumbprint
208 /// https://tools.ietf.org/html/rfc7515#section-4.1.7
209 #[serde(skip_serializing_if = "Option::is_none")]
210 pub x5t: Option<SmallString<27>>, // 27 = base64_encoded_length(20)
211
212 /// X.509 SHA256 certificate Thumbprint
213 /// https://tools.ietf.org/html/rfc7515#section-4.1.8
214 #[serde(skip_serializing_if = "Option::is_none")]
215 #[serde(rename = "x5t#S256")]
216 pub x5t_s256: Option<SmallString<43>>, // 43 = base64_encoded_length(32)
217}
218
219impl Default for Header {
220 fn default() -> Self {
221 Self {
222 typ: TokenType::JWT,
223 alg: Algorithm::EdDSA,
224 cty: None,
225 jku: None,
226 kid: None,
227 x5u: None,
228 x5c: None,
229 x5t: None,
230 x5t_s256: None,
231 }
232 }
233}
234
235/// Registered claim names from https://www.rfc-editor.org/rfc/rfc7519#section-4.1
236#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
237pub struct RegisteredClaims {
238 /// Issuer
239 /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.1
240 #[serde(skip_serializing_if = "Option::is_none")]
241 pub iss: Option<SmallString<20>>,
242
243 /// Subject
244 /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.2
245 #[serde(skip_serializing_if = "Option::is_none")]
246 pub sub: Option<SmallString<36>>, // 36 = UUID length
247
248 /// Audience
249 /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3
250 #[serde(skip_serializing_if = "Option::is_none")]
251 pub aud: Option<SmallString<20>>,
252
253 /// Expiration Time
254 /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4
255 #[serde(skip_serializing_if = "Option::is_none")]
256 pub exp: Option<u64>,
257
258 /// Not Before
259 /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.5
260 #[serde(skip_serializing_if = "Option::is_none")]
261 pub nbf: Option<u64>,
262
263 /// Issued At
264 /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6
265 #[serde(skip_serializing_if = "Option::is_none")]
266 pub iat: Option<u64>,
267
268 /// JWT ID
269 /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7
270 #[serde(skip_serializing_if = "Option::is_none")]
271 pub jti: Option<SmallString<36>>,
272}
273
274#[derive(Debug, Default, PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)]
275pub enum TokenType {
276 #[default]
277 JWT,
278}
279
280/// The algorithms supported for signing / verifying JWTs
281#[derive(Copy, Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
282pub enum Algorithm {
283 /// HMAC using SHA-256
284 HS256,
285
286 /// HMAC using SHA-384
287 HS384,
288
289 /// HMAC using SHA-512
290 HS512,
291
292 /// BLAKE3 in keyed mode
293 BLAKE3,
294
295 /// Edwards-curve Digital Signature Algorithm (EdDSA)
296 EdDSA,
297
298 /// ECDSA using P-256 and SHA-256
299 ES256,
300
301 /// ECDSA using P-384 and SHA-384
302 ES384,
303
304 /// ECDSA using P-521 and SHA-512
305 ES512,
306
307 /// ML-DSA-44
308 #[serde(rename = "ML-DSA-44")]
309 MlDsa44,
310
311 /// ML-DSA-65
312 #[serde(rename = "ML-DSA-65")]
313 MlDsa65,
314
315 /// ML-DSA-87
316 #[serde(rename = "ML-DSA-87")]
317 MlDsa87,
318
319 /// RSASSA-PKCS1-v1.5 with SHA-256
320 RS256,
321
322 /// RSASSA-PKCS1-v1.5 with SHA-384
323 RS384,
324
325 /// RSASSA-PKCS1-v1.5 with SHA-512
326 RS512,
327
328 /// RSASSA-PSS with SHA-256
329 PS256,
330
331 /// RSASSA-PSS with SHA-384
332 PS384,
333
334 /// RSASSA-PSS with SHA-512
335 PS512,
336}
337
338impl Algorithm {
339 /// Returns the size of the signature of the algorithm, or, if the size can vary in size,
340 /// the upper bound supported by this package (e.g. 8192 bits / 1024 bytes for RSA).
341 /// This is used, among other things, to pre-allocate the output buffer to the correct size
342 /// when encoding a JWT.
343 #[inline]
344 pub(crate) fn signature_max_size(&self) -> usize {
345 match self {
346 Algorithm::BLAKE3 => 32,
347 Algorithm::HS256 => 32,
348 Algorithm::HS384 => 48,
349 Algorithm::HS512 => 64,
350 Algorithm::EdDSA => 64,
351 Algorithm::ES256 => 64,
352 Algorithm::ES384 => 96,
353 Algorithm::ES512 => 132,
354 Algorithm::RS256 => 1024,
355 Algorithm::RS384 => 1024,
356 Algorithm::RS512 => 1024,
357 Algorithm::PS256 => 1024,
358 Algorithm::PS384 => 1024,
359 Algorithm::PS512 => 1024,
360 Algorithm::MlDsa44 => 2420,
361 Algorithm::MlDsa65 => 3309,
362 Algorithm::MlDsa87 => 4627,
363 }
364 }
365}
366
367impl core::str::FromStr for Algorithm {
368 type Err = Error;
369
370 fn from_str(s: &str) -> Result<Self, Self::Err> {
371 match s {
372 "BLAKE3" => Ok(Algorithm::BLAKE3),
373 "HS256" => Ok(Algorithm::HS256),
374 "HS384" => Ok(Algorithm::HS384),
375 "HS512" => Ok(Algorithm::HS512),
376 "ES256" => Ok(Algorithm::ES256),
377 "ES384" => Ok(Algorithm::ES384),
378 "ES512" => Ok(Algorithm::ES512),
379 "EdDSA" => Ok(Algorithm::EdDSA),
380 "ML-DSA-44" => Ok(Algorithm::MlDsa44),
381 "ML-DSA-65" => Ok(Algorithm::MlDsa65),
382 "ML-DSA-87" => Ok(Algorithm::MlDsa87),
383 "RS256" => Ok(Algorithm::RS256),
384 "RS384" => Ok(Algorithm::RS384),
385 "RS512" => Ok(Algorithm::RS512),
386 "PS256" => Ok(Algorithm::PS256),
387 "PS384" => Ok(Algorithm::PS384),
388 "PS512" => Ok(Algorithm::PS512),
389 _ => Err(Error::UnknownAlgorithm(s.to_string())),
390 }
391 }
392}
393
394impl core::fmt::Display for Algorithm {
395 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
396 let name = match self {
397 Algorithm::BLAKE3 => "BLAKE3",
398 Algorithm::HS256 => "HS256",
399 Algorithm::HS384 => "HS384",
400 Algorithm::HS512 => "HS512",
401 Algorithm::EdDSA => "EdDSA",
402 Algorithm::ES256 => "ES256",
403 Algorithm::ES384 => "ES384",
404 Algorithm::ES512 => "ES512",
405 Algorithm::MlDsa44 => "ML-DSA-44",
406 Algorithm::MlDsa65 => "ML-DSA-65",
407 Algorithm::MlDsa87 => "ML-DSA-87",
408 Algorithm::RS256 => "RS256",
409 Algorithm::RS384 => "RS384",
410 Algorithm::RS512 => "RS512",
411 Algorithm::PS256 => "PS256",
412 Algorithm::PS384 => "PS384",
413 Algorithm::PS512 => "PS512",
414 };
415
416 f.write_str(name)
417 }
418}
419
420#[derive(Debug)]
421pub enum Error {
422 UnknownAlgorithm(String),
423 InvalidCurve,
424 InvalidTokenType(String),
425 Json(serde_json::Error),
426 InvalidToken,
427 InvalidSignature,
428 InvalidKey,
429 InvalidEllipticCurve(String),
430 InvalidJwk { kid: String, err: String },
431 Unspecified(String),
432 ClockIsMissing,
433}
434
435impl core::fmt::Display for Error {
436 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
437 match self {
438 Error::UnknownAlgorithm(algorithm) => write!(f, "unknown algorithm: {algorithm}"),
439 Error::InvalidCurve => f.write_str("invalid curve"),
440 Error::InvalidTokenType(token_type) => write!(f, "invalid token type: {token_type}"),
441 Error::Json(err) => write!(f, "error serializing JWT to JSON: {err}"),
442 Error::InvalidToken => f.write_str("JWT is not valid"),
443 Error::InvalidSignature => f.write_str("signature is not valid"),
444 Error::InvalidKey => f.write_str("key is not valid"),
445 Error::InvalidEllipticCurve(curve) => write!(f, "invalid elliptic curve: {curve}"),
446 Error::InvalidJwk {
447 kid,
448 err,
449 } => write!(f, "{kid} is not a valid JWK: {err}"),
450 Error::Unspecified(err) => f.write_str(&err),
451 Error::ClockIsMissing => f.write_str("a clock is needed for exp or nbf verification"),
452 }
453 }
454}
455
456impl From<serde_json::Error> for Error {
457 fn from(err: serde_json::Error) -> Self {
458 Self::Json(err)
459 }
460}
461
462#[cfg(feature = "std")]
463impl std::error::Error for Error {}
464
465/// A wall clock used to check tokens expiration.
466///
467/// Returns the current Unix timestamp (seconds since epoch). This trait
468/// exists so that no_std environments can inject their own time source
469/// (hardware RTC, NTP, etc.) instead of relying on `std::time::SystemTime`.
470pub trait Clock: Send + Sync {
471 fn now(&self) -> u64;
472}
473
474/// A [`Clock`] backed by `std::time::SystemTime`.
475///
476/// Available only when the `std` feature is enabled.
477#[cfg(feature = "std")]
478pub struct SystemClock;
479
480#[cfg(feature = "std")]
481impl Clock for SystemClock {
482 #[inline]
483 fn now(&self) -> u64 {
484 std::time::SystemTime::now()
485 .duration_since(std::time::UNIX_EPOCH)
486 .unwrap_or_default()
487 .as_secs()
488 }
489}
490
491pub struct VerifyOptions<'a> {
492 /// Allowed time drift for `nbf` and `exp` verification in order to account for devices with
493 /// inacurate clocks.
494 /// default: 30 seconds
495 pub allowed_time_drift: Duration,
496 /// default: true
497 pub nbf: bool,
498 /// default: true
499 pub exp: bool,
500 /// default: None
501 pub aud: Option<&'a [&'a str]>,
502 /// default: None
503 pub iss: Option<&'a [&'a str]>,
504 /// default: Some(&SYSTEM_CLOCK)
505 pub clock: Option<&'a dyn Clock>,
506}
507
508#[cfg(feature = "std")]
509impl Default for VerifyOptions<'_> {
510 fn default() -> Self {
511 Self {
512 allowed_time_drift: core::time::Duration::from_secs(30),
513 nbf: true,
514 exp: true,
515 aud: None,
516 iss: None,
517 clock: Some(&SYSTEM_CLOCK),
518 }
519 }
520}
521
522pub fn sign<C: Serialize>(key: &dyn Signer, header: &Header, claims: &C) -> Result<String, Error> {
523 let signing_algorithm = key.algorithm();
524 if signing_algorithm != header.alg {
525 return Err(Error::InvalidKey);
526 }
527
528 let header_base64 = base64::encode(serde_json::to_string(header)?.as_bytes(), base64::Alphabet::UrlNoPadding);
529 let claims_base64 = base64::encode(serde_json::to_string(claims)?.as_bytes(), base64::Alphabet::UrlNoPadding);
530
531 let mut jwt = String::with_capacity(
532 header_base64.len()
533 + claims_base64.len()
534 + base64::encoded_length(signing_algorithm.signature_max_size(), false)
535 .expect("error getting base64 encoding length")
536 + 2,
537 );
538 jwt.push_str(&header_base64);
539 jwt.push('.');
540 jwt.push_str(&claims_base64);
541
542 let signature = key.sign(jwt.as_bytes())?;
543 jwt.push('.');
544 jwt.push_str(&base64::encode(signature.as_ref(), base64::Alphabet::UrlNoPadding));
545
546 return Ok(jwt);
547}
548
549pub fn parse_header(token: &str) -> Result<Header, Error> {
550 let mut parts = token.split('.');
551 let header_base64 = parts.next().ok_or(Error::InvalidToken)?;
552 if parts.count() != 2 {
553 return Err(Error::InvalidToken);
554 }
555
556 let header_json = base64::decode(header_base64, base64::Alphabet::UrlNoPadding).map_err(|_| Error::InvalidToken)?;
557 let header: Header = serde_json::from_slice(&header_json).map_err(|_| Error::InvalidToken)?;
558
559 return Ok(header);
560}
561
562pub fn parse_and_verify<C: DeserializeOwned>(
563 key: &dyn Verifier,
564 header: &Header,
565 token: &str,
566 verify_options: &VerifyOptions,
567) -> Result<C, Error> {
568 if (verify_options.exp || verify_options.nbf) && verify_options.clock.is_none() {
569 return Err(Error::ClockIsMissing);
570 }
571
572 if header.alg != key.algorithm() {
573 return Err(Error::InvalidToken);
574 }
575
576 let mut parts = token.split('.');
577 let header_base64 = parts.next().ok_or(Error::InvalidToken)?;
578 let claims_base64 = parts.next().ok_or(Error::InvalidToken)?;
579 let signature_base64 = parts.next().ok_or(Error::InvalidToken)?;
580 if parts.next().is_some() {
581 return Err(Error::InvalidToken);
582 }
583
584 let mut signature_buffer = [0u8; SIGNATURE_MAX_SIZE];
585 let signature_size = base64::decode_into(
586 &mut signature_buffer,
587 signature_base64.as_bytes(),
588 base64::Alphabet::UrlNoPadding,
589 )
590 .map_err(|_| Error::InvalidSignature)?;
591
592 let signed_message = &token[..header_base64.len() + 1 + claims_base64.len()].as_bytes();
593 key.verify(signed_message, &signature_buffer[..signature_size])
594 .map_err(|_| Error::InvalidSignature)?;
595
596 let claims_json =
597 base64::decode(&claims_base64, base64::Alphabet::UrlNoPadding).map_err(|_| Error::InvalidToken)?;
598
599 let claims =
600 if verify_options.exp || verify_options.nbf || verify_options.aud.is_some() || verify_options.iss.is_some() {
601 let claims_json_value: serde_json::Value =
602 serde_json::from_slice(&claims_json).map_err(|_| Error::InvalidToken)?;
603
604 match &claims_json_value {
605 serde_json::Value::Object(claims_object) => {
606 if verify_options.exp {
607 match claims_object.get("exp") {
608 None => return Err(Error::InvalidToken),
609 Some(exp_value) => {
610 if let Some(exp) = exp_value.as_u64() {
611 let now = verify_options.clock.unwrap().now();
612 if exp < (now - verify_options.allowed_time_drift.as_secs()) {
613 return Err(Error::InvalidToken);
614 }
615 } else {
616 return Err(Error::InvalidToken);
617 }
618 }
619 }
620 }
621
622 if verify_options.nbf {
623 match claims_object.get("nbf") {
624 None => return Err(Error::InvalidToken),
625 Some(nbf_value) => {
626 if let Some(nbf) = nbf_value.as_u64() {
627 let now = verify_options.clock.unwrap().now();
628 if nbf > (now + verify_options.allowed_time_drift.as_secs()) {
629 return Err(Error::InvalidToken);
630 }
631 } else {
632 return Err(Error::InvalidToken);
633 }
634 }
635 }
636 }
637
638 if let Some(expected_aud) = verify_options.aud {
639 match claims_object.get("aud") {
640 None => return Err(Error::InvalidToken),
641 Some(aud_value) => {
642 if let Some(aud) = aud_value.as_str() {
643 if !expected_aud.contains(&aud) {
644 return Err(Error::InvalidToken);
645 }
646 } else {
647 return Err(Error::InvalidToken);
648 }
649 }
650 }
651 }
652
653 if let Some(expected_iss) = verify_options.iss {
654 match claims_object.get("iss") {
655 None => return Err(Error::InvalidToken),
656 Some(iss_value) => {
657 if let Some(iss) = iss_value.as_str() {
658 if !expected_iss.contains(&iss) {
659 return Err(Error::InvalidToken);
660 }
661 } else {
662 return Err(Error::InvalidToken);
663 }
664 }
665 }
666 }
667 }
668 _ => return Err(Error::InvalidToken),
669 };
670
671 serde_json::from_value(claims_json_value).map_err(|_| Error::InvalidToken)?
672 } else {
673 serde_json::from_slice(&claims_json).map_err(|_| Error::InvalidToken)?
674 };
675
676 return Ok(claims);
677}