Skip to main content

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//! `jwt` still requires `alloc`. ML-DSA signing additionally requires a random
15//! number generator: enable the `random` feature (implied by `std`), or provide
16//! a `getrandom` backend. Without `random`, the ML-DSA secret-key variants of
17//! [`Key`] and the ML-DSA [`Signer`] implementations are not compiled.
18//!
19//! # Example
20//!
21//! ```
22//! # #[cfg(feature = "std")] {
23//! use jwt::*;
24//! use crypto::curve25519::ed25519;
25//!
26//!     // 1. Generate an Ed25519 secret key.
27//!     let secret_key = ed25519::SecretKey::generate().map_err(|_| Error::InvalidKey)?;
28//!
29//!     // 2. Build the header.
30//!     let header = Header {
31//!         typ: TokenType::JWT,
32//!         alg: Algorithm::EdDSA,
33//!         kid: Some("my-key-id".into()),
34//!         cty: None,
35//!         jku: None,
36//!         x5u: None,
37//!         x5c: None,
38//!         x5t: None,
39//!         x5t_s256: None,
40//!     };
41//!
42//!     // 3. Define the claims and sign.
43//!     let claims = serde_json::json!({ "sub": "user123", "exp": 9999999999_u64 });
44//!     let token = sign(&secret_key, &header, &claims)?;
45//!
46//!     // 4. Extract the public key for verification.
47//!     let public_key = secret_key.public_key();
48//!
49//!     // 5. Parse only the header first (e.g., to read `kid` for key lookup).
50//!     let parsed_header = parse_header(&token)?;
51//!     assert_eq!(parsed_header.kid.as_deref(), Some("my-key-id"));
52//!
53//!     // 6. Now verify and deserialize the claims.
54//!     let opts = VerifyOptions {
55//!         allowed_time_drift: core::time::Duration::from_secs(60),
56//!         exp: true,
57//!         nbf: false,
58//!         aud: None,
59//!         iss: None,
60//!         clock: Some(&jwt::SYSTEM_CLOCK),
61//!     };
62//!     let claims: serde_json::Value =
63//!         parse_and_verify(&public_key, &parsed_header, &token, &opts)?;
64//!     assert_eq!(claims["sub"], "user123");
65//! # }
66//! # Ok::<(), jwt::Error>(())
67//! ```
68//!
69//! # JSON Web Key (JWK) import and export
70//!
71//! Keys can be exported to and imported from JSON Web Keys (JWK) for publishing or later re-use.
72//! Every supported key type implements `From<&KeyType> for Jwk`, and the reverse conversion is
73//! available through `TryFrom<&Jwk>`. Use it when the key is only known at runtime, for example
74//! after fetching a JWKS document. P-256, P-384 and P-521 public keys are all supported.
75//!
76//! ```
77//! # #[cfg(feature = "std")] {
78//! use jwt::*;
79//! use crypto::p256;
80//!
81//!     // Generate a P-256 key pair.
82//!     let secret_key = p256::SecretKey::generate().map_err(|_| Error::InvalidKey)?;
83//!     let public_key = secret_key.public_key();
84//!
85//!     // Convert to a JWK (e.g. for publishing in a JWKS endpoint).
86//!     let jwk = Jwk::from(&public_key);
87//!     assert_eq!(jwk.algorithm, Algorithm::ES256);
88//!
89//!     // Parse the JWK back into a key (e.g. from a JWKS response).
90//!     let key = p256::PublicKey::try_from(&jwk)?;
91//!
92//!     let header = Header { typ: TokenType::JWT, alg: Algorithm::ES256, ..Default::default() };
93//!     let token = sign(&secret_key, &header, &serde_json::json!({"exp": 9999999999_u64, "nbf": 0_u64 }))?;
94//!     let parsed_header = parse_header(&token)?;
95//!     let _claims: serde_json::Value = parse_and_verify(&key, &parsed_header, &token, &VerifyOptions::default())?;
96//! # }
97//! # Ok::<(), jwt::Error>(())
98//! ```
99//!
100//! When the key type is not known ahead of time (for example a JWKS document that may contain
101//! several kinds of keys), use the [`Key`] enum. It inspects the JWK's `kty` and `crv` and selects the
102//! matching concrete key, preferring the secret variant when both halves are present. [`Key`]
103//! implements both [`Signer`] and [`Verifier`], so it can be passed straight to [`sign`] or
104//! [`parse_and_verify`]:
105//!
106//! ```
107//! # #[cfg(feature = "std")] {
108//! use jwt::*;
109//! use crypto::curve25519::ed25519;
110//!
111//!     let secret_key = ed25519::SecretKey::generate().map_err(|_| Error::InvalidKey)?;
112//!
113//!     // A JWKS entry whose key type is only known at runtime.
114//!     let jwk = Jwk::from(&secret_key.public_key());
115//!     let key = Key::try_from(&jwk)?;
116//!     assert!(matches!(key, Key::Ed25519Public(_)));
117//!
118//!     let header = Header { typ: TokenType::JWT, alg: Algorithm::EdDSA, ..Default::default() };
119//!     let token = sign(&secret_key, &header, &serde_json::json!({"exp": 9999999999_u64, "nbf": 0_u64 }))?;
120//!     let parsed_header = parse_header(&token)?;
121//!     let _claims: serde_json::Value = parse_and_verify(&key, &parsed_header, &token, &VerifyOptions::default())?;
122//! # }
123//! # Ok::<(), jwt::Error>(())
124//! ```
125//!
126//! When a JWK derived from a secret key is decoded, the secret variant is preferred, so the same
127//! [`Key`] can be used for signing:
128//!
129//! ```
130//! # #[cfg(feature = "std")] {
131//! use jwt::*;
132//! use crypto::curve25519::ed25519;
133//!
134//!     let secret_key = ed25519::SecretKey::generate().map_err(|_| Error::InvalidKey)?;
135//!     let jwk = Jwk::from(&secret_key);
136//!     let key = Key::try_from(&jwk)?;
137//!     assert!(matches!(key, Key::Ed25519Secret(_)));
138//!
139//!     let header = Header { typ: TokenType::JWT, alg: Algorithm::EdDSA, ..Default::default() };
140//!     let token = sign(&key, &header, &serde_json::json!({"exp": 9999999999_u64, "nbf": 0_u64 }))?;
141//!     let parsed_header = parse_header(&token)?;
142//!     let _claims: serde_json::Value = parse_and_verify(&key, &parsed_header, &token, &VerifyOptions::default())?;
143//! # }
144//! # Ok::<(), jwt::Error>(())
145//! ```
146
147#![cfg_attr(not(feature = "std"), no_std)]
148
149extern crate alloc;
150
151use alloc::{
152    string::{String, ToString},
153    vec::Vec,
154};
155use core::time::Duration;
156
157use serde::{Deserialize, Serialize, de::DeserializeOwned};
158use small_collections::SmallString;
159
160mod jwk;
161mod jwt_crypto;
162
163pub use jwk::*;
164pub use jwt_crypto::*;
165
166#[cfg(feature = "std")]
167pub static SYSTEM_CLOCK: SystemClock = SystemClock;
168
169#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
170pub struct Header {
171    /// The only valid value is "JWT"
172    /// https://tools.ietf.org/html/rfc7519#section-5.1
173    pub typ: TokenType,
174
175    /// ttps://tools.ietf.org/html/rfc7515#section-4.1.1
176    pub alg: Algorithm,
177
178    /// Content type
179    /// https://tools.ietf.org/html/rfc7519#section-5.2
180    #[serde(skip_serializing_if = "Option::is_none")]
181    pub cty: Option<SmallString<3>>,
182
183    /// JSON Key URL
184    /// https://tools.ietf.org/html/rfc7515#section-4.1.2
185    #[serde(skip_serializing_if = "Option::is_none")]
186    pub jku: Option<String>,
187
188    /// JSON Web Key
189    /// https://tools.ietf.org/html/rfc7515#section-4.1.3
190    // #[serde(skip_serializing_if = "Option::is_none")]
191    // pub jwk: Option<Jwk>,
192
193    /// Key ID
194    /// https://tools.ietf.org/html/rfc7515#section-4.1.4
195    #[serde(skip_serializing_if = "Option::is_none")]
196    pub kid: Option<SmallString<36>>, // 36 = UUID length
197
198    /// X.509 URL
199    /// https://tools.ietf.org/html/rfc7515#section-4.1.5
200    #[serde(skip_serializing_if = "Option::is_none")]
201    pub x5u: Option<String>,
202
203    /// X.509 certificate chain.
204    /// https://tools.ietf.org/html/rfc7515#section-4.1.6
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub x5c: Option<Vec<String>>,
207
208    /// X.509 SHA1 certificate Thumbprint
209    /// https://tools.ietf.org/html/rfc7515#section-4.1.7
210    #[serde(skip_serializing_if = "Option::is_none")]
211    pub x5t: Option<SmallString<27>>, // 27 = base64_encoded_length(20)
212
213    /// X.509 SHA256 certificate Thumbprint
214    /// https://tools.ietf.org/html/rfc7515#section-4.1.8
215    #[serde(skip_serializing_if = "Option::is_none")]
216    #[serde(rename = "x5t#S256")]
217    pub x5t_s256: Option<SmallString<43>>, // 43 = base64_encoded_length(32)
218}
219
220impl Default for Header {
221    fn default() -> Self {
222        Self {
223            typ: TokenType::JWT,
224            alg: Algorithm::EdDSA,
225            cty: None,
226            jku: None,
227            kid: None,
228            x5u: None,
229            x5c: None,
230            x5t: None,
231            x5t_s256: None,
232        }
233    }
234}
235
236/// Registered claim names from https://www.rfc-editor.org/rfc/rfc7519#section-4.1
237#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
238pub struct RegisteredClaims {
239    /// Issuer
240    /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.1
241    #[serde(skip_serializing_if = "Option::is_none")]
242    pub iss: Option<SmallString<20>>,
243
244    /// Subject
245    /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.2
246    #[serde(skip_serializing_if = "Option::is_none")]
247    pub sub: Option<SmallString<36>>, // 36 = UUID length
248
249    /// Audience
250    /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3
251    #[serde(skip_serializing_if = "Option::is_none")]
252    pub aud: Option<SmallString<20>>,
253
254    /// Expiration Time
255    /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4
256    #[serde(skip_serializing_if = "Option::is_none")]
257    pub exp: Option<u64>,
258
259    /// Not Before
260    /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.5
261    #[serde(skip_serializing_if = "Option::is_none")]
262    pub nbf: Option<u64>,
263
264    /// Issued At
265    /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6
266    #[serde(skip_serializing_if = "Option::is_none")]
267    pub iat: Option<u64>,
268
269    /// JWT ID
270    /// https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7
271    #[serde(skip_serializing_if = "Option::is_none")]
272    pub jti: Option<SmallString<36>>,
273}
274
275#[derive(Debug, Default, PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)]
276pub enum TokenType {
277    #[default]
278    JWT,
279}
280
281/// The algorithms supported for signing / verifying JWTs
282#[derive(Copy, Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
283pub enum Algorithm {
284    /// HMAC using SHA-256
285    HS256,
286
287    /// HMAC using SHA-384
288    HS384,
289
290    /// HMAC using SHA-512
291    HS512,
292
293    /// BLAKE3 in keyed mode
294    BLAKE3,
295
296    /// Edwards-curve Digital Signature Algorithm (EdDSA)
297    EdDSA,
298
299    /// ECDSA using P-256 and SHA-256
300    ES256,
301
302    /// ECDSA using P-384 and SHA-384
303    ES384,
304
305    /// ECDSA using P-521 and SHA-512
306    ES512,
307
308    /// ML-DSA-44
309    #[serde(rename = "ML-DSA-44")]
310    MlDsa44,
311
312    /// ML-DSA-65
313    #[serde(rename = "ML-DSA-65")]
314    MlDsa65,
315
316    /// ML-DSA-87
317    #[serde(rename = "ML-DSA-87")]
318    MlDsa87,
319
320    /// RSASSA-PKCS1-v1.5 with SHA-256
321    RS256,
322
323    /// RSASSA-PKCS1-v1.5 with SHA-384
324    RS384,
325
326    /// RSASSA-PKCS1-v1.5 with SHA-512
327    RS512,
328
329    /// RSASSA-PSS with SHA-256
330    PS256,
331
332    /// RSASSA-PSS with SHA-384
333    PS384,
334
335    /// RSASSA-PSS with SHA-512
336    PS512,
337}
338
339impl Algorithm {
340    /// Returns the size of the signature of the algorithm, or, if the size can vary in size,
341    /// the upper bound supported by this package (e.g. 8192 bits / 1024 bytes for RSA).
342    /// This is used, among other things, to pre-allocate the output buffer to the correct size
343    /// when encoding a JWT.
344    #[inline]
345    pub(crate) fn signature_max_size(&self) -> usize {
346        match self {
347            Algorithm::BLAKE3 => 32,
348            Algorithm::HS256 => 32,
349            Algorithm::HS384 => 48,
350            Algorithm::HS512 => 64,
351            Algorithm::EdDSA => 64,
352            Algorithm::ES256 => 64,
353            Algorithm::ES384 => 96,
354            Algorithm::ES512 => 132,
355            Algorithm::RS256 => 1024,
356            Algorithm::RS384 => 1024,
357            Algorithm::RS512 => 1024,
358            Algorithm::PS256 => 1024,
359            Algorithm::PS384 => 1024,
360            Algorithm::PS512 => 1024,
361            Algorithm::MlDsa44 => 2420,
362            Algorithm::MlDsa65 => 3309,
363            Algorithm::MlDsa87 => 4627,
364        }
365    }
366}
367
368impl core::str::FromStr for Algorithm {
369    type Err = Error;
370
371    fn from_str(s: &str) -> Result<Self, Self::Err> {
372        match s {
373            "BLAKE3" => Ok(Algorithm::BLAKE3),
374            "HS256" => Ok(Algorithm::HS256),
375            "HS384" => Ok(Algorithm::HS384),
376            "HS512" => Ok(Algorithm::HS512),
377            "ES256" => Ok(Algorithm::ES256),
378            "ES384" => Ok(Algorithm::ES384),
379            "ES512" => Ok(Algorithm::ES512),
380            "EdDSA" => Ok(Algorithm::EdDSA),
381            "ML-DSA-44" => Ok(Algorithm::MlDsa44),
382            "ML-DSA-65" => Ok(Algorithm::MlDsa65),
383            "ML-DSA-87" => Ok(Algorithm::MlDsa87),
384            "RS256" => Ok(Algorithm::RS256),
385            "RS384" => Ok(Algorithm::RS384),
386            "RS512" => Ok(Algorithm::RS512),
387            "PS256" => Ok(Algorithm::PS256),
388            "PS384" => Ok(Algorithm::PS384),
389            "PS512" => Ok(Algorithm::PS512),
390            _ => Err(Error::UnknownAlgorithm(s.to_string())),
391        }
392    }
393}
394
395impl core::fmt::Display for Algorithm {
396    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
397        let name = match self {
398            Algorithm::BLAKE3 => "BLAKE3",
399            Algorithm::HS256 => "HS256",
400            Algorithm::HS384 => "HS384",
401            Algorithm::HS512 => "HS512",
402            Algorithm::EdDSA => "EdDSA",
403            Algorithm::ES256 => "ES256",
404            Algorithm::ES384 => "ES384",
405            Algorithm::ES512 => "ES512",
406            Algorithm::MlDsa44 => "ML-DSA-44",
407            Algorithm::MlDsa65 => "ML-DSA-65",
408            Algorithm::MlDsa87 => "ML-DSA-87",
409            Algorithm::RS256 => "RS256",
410            Algorithm::RS384 => "RS384",
411            Algorithm::RS512 => "RS512",
412            Algorithm::PS256 => "PS256",
413            Algorithm::PS384 => "PS384",
414            Algorithm::PS512 => "PS512",
415        };
416
417        f.write_str(name)
418    }
419}
420
421#[derive(Debug)]
422pub enum Error {
423    UnknownAlgorithm(String),
424    InvalidCurve,
425    InvalidTokenType(String),
426    Json(serde_json::Error),
427    InvalidToken,
428    InvalidSignature,
429    InvalidKey,
430    InvalidEllipticCurve(String),
431    InvalidJwk { kid: String, err: String },
432    Unspecified(String),
433    ClockIsMissing,
434}
435
436impl core::fmt::Display for Error {
437    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
438        match self {
439            Error::UnknownAlgorithm(algorithm) => write!(f, "unknown algorithm: {algorithm}"),
440            Error::InvalidCurve => f.write_str("invalid curve"),
441            Error::InvalidTokenType(token_type) => write!(f, "invalid token type: {token_type}"),
442            Error::Json(err) => write!(f, "error serializing JWT to JSON: {err}"),
443            Error::InvalidToken => f.write_str("JWT is not valid"),
444            Error::InvalidSignature => f.write_str("signature is not valid"),
445            Error::InvalidKey => f.write_str("key is not valid"),
446            Error::InvalidEllipticCurve(curve) => write!(f, "invalid elliptic curve: {curve}"),
447            Error::InvalidJwk {
448                kid,
449                err,
450            } => write!(f, "{kid} is not a valid JWK: {err}"),
451            Error::Unspecified(err) => f.write_str(err),
452            Error::ClockIsMissing => f.write_str("a clock is needed for exp or nbf verification"),
453        }
454    }
455}
456
457impl From<serde_json::Error> for Error {
458    fn from(err: serde_json::Error) -> Self {
459        Self::Json(err)
460    }
461}
462
463impl core::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 = base64::decode(claims_base64, base64::Alphabet::UrlNoPadding).map_err(|_| Error::InvalidToken)?;
597
598    let claims =
599        if verify_options.exp || verify_options.nbf || verify_options.aud.is_some() || verify_options.iss.is_some() {
600            let claims_json_value: serde_json::Value =
601                serde_json::from_slice(&claims_json).map_err(|_| Error::InvalidToken)?;
602
603            match &claims_json_value {
604                serde_json::Value::Object(claims_object) => {
605                    if verify_options.exp {
606                        match claims_object.get("exp") {
607                            None => return Err(Error::InvalidToken),
608                            Some(exp_value) => {
609                                if let Some(exp) = exp_value.as_u64() {
610                                    let now = verify_options.clock.unwrap().now();
611                                    if exp < (now - verify_options.allowed_time_drift.as_secs()) {
612                                        return Err(Error::InvalidToken);
613                                    }
614                                } else {
615                                    return Err(Error::InvalidToken);
616                                }
617                            }
618                        }
619                    }
620
621                    if verify_options.nbf {
622                        match claims_object.get("nbf") {
623                            None => return Err(Error::InvalidToken),
624                            Some(nbf_value) => {
625                                if let Some(nbf) = nbf_value.as_u64() {
626                                    let now = verify_options.clock.unwrap().now();
627                                    if nbf > (now + verify_options.allowed_time_drift.as_secs()) {
628                                        return Err(Error::InvalidToken);
629                                    }
630                                } else {
631                                    return Err(Error::InvalidToken);
632                                }
633                            }
634                        }
635                    }
636
637                    if let Some(expected_aud) = verify_options.aud {
638                        match claims_object.get("aud") {
639                            None => return Err(Error::InvalidToken),
640                            Some(aud_value) => {
641                                if let Some(aud) = aud_value.as_str() {
642                                    if !expected_aud.contains(&aud) {
643                                        return Err(Error::InvalidToken);
644                                    }
645                                } else {
646                                    return Err(Error::InvalidToken);
647                                }
648                            }
649                        }
650                    }
651
652                    if let Some(expected_iss) = verify_options.iss {
653                        match claims_object.get("iss") {
654                            None => return Err(Error::InvalidToken),
655                            Some(iss_value) => {
656                                if let Some(iss) = iss_value.as_str() {
657                                    if !expected_iss.contains(&iss) {
658                                        return Err(Error::InvalidToken);
659                                    }
660                                } else {
661                                    return Err(Error::InvalidToken);
662                                }
663                            }
664                        }
665                    }
666                }
667                _ => return Err(Error::InvalidToken),
668            };
669
670            serde_json::from_value(claims_json_value).map_err(|_| Error::InvalidToken)?
671        } else {
672            serde_json::from_slice(&claims_json).map_err(|_| Error::InvalidToken)?
673        };
674
675    return Ok(claims);
676}