pub(super) fn verified_claims<'b, AC, GC, JE>(
        &self,
        jwt: &'b JsonWebToken<
            IdTokenClaims<AC, GC>,
            JE,
            JS,
            JT,
            JsonWebTokenJsonPayloadDeserializer,
        >,
        nonce: Option<&Nonce>,
    ) -> Result<&'b IdTokenClaims<AC, GC>, ClaimsVerificationError>
    where
        AC: AdditionalClaims,
        GC: GenderClaim,
        JE: JweContentEncryptionAlgorithm,
    {
        // The code below roughly follows the validation steps described in
        // https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation

        // Steps 1--3 are handled by the generic JwtClaimsVerifier.
        let partially_verified_claims = self.jwt_verifier.verified_claims(jwt)?;

        // 4. If the ID Token contains multiple audiences, the Client SHOULD verify that an azp
        //    Claim is present.

        // FIXME(docs): add a reference in the module documentation describing this intentional
        // deviation from the spec.

        // There is significant confusion and contradiction in the OpenID Connect Core spec around
        // the azp claim. See https://bitbucket.org/openid/connect/issues/973/ for a detailed
        // discussion. Given the lack of clarity around how this claim should be used, we defer
        // any verification of it here until a use case becomes apparent. If such a use case does
        // arise, we most likely want to allow clients to pass in a function for validating the
        // azp claim rather than introducing logic that affects all clients of this library.

        // This naive implementation of the spec would almost certainly not be useful in practice:
        /*
        let azp_required = partially_verified_claims.audiences().len() > 1;

        // 5. If an azp (authorized party) Claim is present, the Client SHOULD verify that its
        //    client_id is the Claim Value.
        if let Some(authorized_party) = partially_verified_claims.authorized_party() {
            if *authorized_party != self.client_id {
                return Err(ClaimsVerificationError::InvalidAudience(format!(
                    "authorized party must match client ID `{}` (found `{}`",
                    *self.client_id, **authorized_party
                )));
            }
        } else if azp_required {
            return Err(ClaimsVerificationError::InvalidAudience(format!(
                "missing authorized party claim but multiple audiences found"
            )));
        }
        */

        // Steps 6--8 are handled by the generic JwtClaimsVerifier.

        // 9. The current time MUST be before the time represented by the exp Claim.
        let cur_time = (*self.time_fn)();
        if let Ok(expiration) = partially_verified_claims.expiration() {
            if cur_time > expiration {
                return Err(ClaimsVerificationError::Expired(format!(
                    "ID token expired at {} (current time is {})",
                    expiration, cur_time
                )));
            }
        } else {
            return Err(ClaimsVerificationError::Other(
                "expiration out of bounds".to_string(),
            ));
        }

        // 10. The iat Claim can be used to reject tokens that were issued too far away from the
        //     current time, limiting the amount of time that nonces need to be stored to prevent
        //     attacks. The acceptable range is Client specific.
        if let Ok(ref issue_time) = partially_verified_claims.issue_time() {
            (*self.iat_verifier_fn)(issue_time).map_err(ClaimsVerificationError::Expired)?;
        } else {
            return Err(ClaimsVerificationError::Other(
                "issue time out of bounds".to_string(),
            ));
        }

        // 11. If a nonce value was sent in the Authentication Request, a nonce Claim MUST be
        //     present and its value checked to verify that it is the same value as the one that was
        //     sent in the Authentication Request. The Client SHOULD check the nonce value for
        //     replay attacks. The precise method for detecting replay attacks is Client specific.
        if let Some(expected_nonce) = nonce {
            if let Some(claims_nonce) = partially_verified_claims.nonce() {
                if claims_nonce != expected_nonce {
                    return Err(ClaimsVerificationError::InvalidNonce(
                        "nonce mismatch".to_string(),
                    ));
                }
            } else {
                return Err(ClaimsVerificationError::InvalidNonce(
                    "missing nonce claim".to_string(),
                ));
            }
        }

        // 12. If the acr Claim was requested, the Client SHOULD check that the asserted Claim Value
        //     is appropriate. The meaning and processing of acr Claim Values is out of scope for
        //     this specification.
        (*self.acr_verifier_fn)(partially_verified_claims.auth_context_ref())
            .map_err(ClaimsVerificationError::InvalidAuthContext)?;

        // 13. If the auth_time Claim was requested, either through a specific request for this
        //     Claim or by using the max_age parameter, the Client SHOULD check the auth_time Claim
        //     value and request re-authentication if it determines too much time has elapsed since
        //     the last End-User authentication.
        match partially_verified_claims.auth_time() {
            Some(ref auth_time_result) => auth_time_result
                .map(|auth_time| (*self.auth_time_verifier_fn)(Some(&auth_time)))
                .map_err(|_| ClaimsVerificationError::Other("auth time out of bounds".to_string()))?
                .map_err(ClaimsVerificationError::InvalidAuthTime)?,
            None => (*self.auth_time_verifier_fn)(None)
                .map_err(ClaimsVerificationError::InvalidAuthTime)?,
        };

        Ok(partially_verified_claims)
    }
// TODO: Add a version that accepts a nonce validation function. Some client applications may
// use crypto or some other mechanism to validate nonces instead of storing every nonce.
Add a version that accepts a nonce validation function. Some client applications may
use crypto or some other mechanism to validate nonces instead of storing every nonce.
Add a version that accepts a nonce validation function . Some client applications may use crypto or some other mechanism to validate nonces instead of storing every nonce .
pub(super) fn verified_claims<'b, AC, GC, JE>(
        &self,
        jwt: &'b JsonWebToken<
            IdTokenClaims<AC, GC>,
            JE,
            JS,
            JT,
            JsonWebTokenJsonPayloadDeserializer,
        >,
        nonce: Option<&Nonce>,
    ) -> Result<&'b IdTokenClaims<AC, GC>, ClaimsVerificationError>
    where
        AC: AdditionalClaims,
        GC: GenderClaim,
        JE: JweContentEncryptionAlgorithm,
    {
        // The code below roughly follows the validation steps described in
        // https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
        // Steps 1--3 are handled by the generic JwtClaimsVerifier.
        let partially_verified_claims = self.jwt_verifier.verified_claims(jwt)?;
        // 4. If the ID Token contains multiple audiences, the Client SHOULD verify that an azp
        //    Claim is present.
        // FIXME(docs): add a reference in the module documentation describing this intentional
        // deviation from the spec.
        // There is significant confusion and contradiction in the OpenID Connect Core spec around
        // the azp claim. See https://bitbucket.org/openid/connect/issues/973/ for a detailed
        // discussion. Given the lack of clarity around how this claim should be used, we defer
        // any verification of it here until a use case becomes apparent. If such a use case does
        // arise, we most likely want to allow clients to pass in a function for validating the
        // azp claim rather than introducing logic that affects all clients of this library.
        // This naive implementation of the spec would almost certainly not be useful in practice:
        /*
        let azp_required = partially_verified_claims.audiences().len() > 1;
        // 5. If an azp (authorized party) Claim is present, the Client SHOULD verify that its
        //    client_id is the Claim Value.
        if let Some(authorized_party) = partially_verified_claims.authorized_party() {
            if *authorized_party != self.client_id {
                return Err(ClaimsVerificationError::InvalidAudience(format!(
                    "authorized party must match client ID `{}` (found `{}`",
                    *self.client_id, **authorized_party
                )));
            }
        } else if azp_required {
            return Err(ClaimsVerificationError::InvalidAudience(format!(
                "missing authorized party claim but multiple audiences found"
            )));
        }
        */
        // Steps 6--8 are handled by the generic JwtClaimsVerifier.
        // 9. The current time MUST be before the time represented by the exp Claim.
        let cur_time = (*self.time_fn)();
        if let Ok(expiration) = partially_verified_claims.expiration() {
            if cur_time > expiration {
                return Err(ClaimsVerificationError::Expired(format!(
                    "ID token expired at {} (current time is {})",
                    expiration, cur_time
                )));
            }
        } else {
            return Err(ClaimsVerificationError::Other(
                "expiration out of bounds".to_string(),
            ));
        }
        // 10. The iat Claim can be used to reject tokens that were issued too far away from the
        //     current time, limiting the amount of time that nonces need to be stored to prevent
        //     attacks. The acceptable range is Client specific.
        if let Ok(ref issue_time) = partially_verified_claims.issue_time() {
            (*self.iat_verifier_fn)(issue_time).map_err(ClaimsVerificationError::Expired)?;
        } else {
            return Err(ClaimsVerificationError::Other(
                "issue time out of bounds".to_string(),
            ));
        }
        // 11. If a nonce value was sent in the Authentication Request, a nonce Claim MUST be
        //     present and its value checked to verify that it is the same value as the one that was
        //     sent in the Authentication Request. The Client SHOULD check the nonce value for
        //     replay attacks. The precise method for detecting replay attacks is Client specific.
        if let Some(expected_nonce) = nonce {
            if let Some(claims_nonce) = partially_verified_claims.nonce() {
                if claims_nonce != expected_nonce {
                    return Err(ClaimsVerificationError::InvalidNonce(
                        "nonce mismatch".to_string(),
                    ));
                }
            } else {
                return Err(ClaimsVerificationError::InvalidNonce(
                    "missing nonce claim".to_string(),
                ));
            }
        }
        // 12. If the acr Claim was requested, the Client SHOULD check that the asserted Claim Value
        //     is appropriate. The meaning and processing of acr Claim Values is out of scope for
        //     this specification.
        (*self.acr_verifier_fn)(partially_verified_claims.auth_context_ref())
            .map_err(ClaimsVerificationError::InvalidAuthContext)?;
        // 13. If the auth_time Claim was requested, either through a specific request for this
        //     Claim or by using the max_age parameter, the Client SHOULD check the auth_time Claim
        //     value and request re-authentication if it determines too much time has elapsed since
        //     the last End-User authentication.
        match partially_verified_claims.auth_time() {
            Some(ref auth_time_result) => auth_time_result
                .map(|auth_time| (*self.auth_time_verifier_fn)(Some(&auth_time)))
                .map_err(|_| ClaimsVerificationError::Other("auth time out of bounds".to_string()))?
                .map_err(ClaimsVerificationError::InvalidAuthTime)?,
            None => (*self.auth_time_verifier_fn)(None)
                .map_err(ClaimsVerificationError::InvalidAuthTime)?,
        };
        Ok(partially_verified_claims)
    }
pub ( super ) fn verified_claims < ' b , AC , GC , JE > ( & self , jwt : & ' b JsonWebToken < IdTokenClaims < AC , GC > , JE , JS , JT , JsonWebTokenJsonPayloadDeserializer , > , nonce : Option < & Nonce > , ) -> Result < & ' b IdTokenClaims < AC , GC > , ClaimsVerificationError > where AC : AdditionalClaims , GC : GenderClaim , JE : JweContentEncryptionAlgorithm , { // The code below roughly follows the validation steps described in // https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation // Steps 1--3 are handled by the generic JwtClaimsVerifier. let partially_verified_claims = self . jwt_verifier . verified_claims ( jwt ) ? ; // 4. If the ID Token contains multiple audiences, the Client SHOULD verify that an azp //    Claim is present. // FIXME(docs): add a reference in the module documentation describing this intentional // deviation from the spec. // There is significant confusion and contradiction in the OpenID Connect Core spec around // the azp claim. See https://bitbucket.org/openid/connect/issues/973/ for a detailed // discussion. Given the lack of clarity around how this claim should be used, we defer // any verification of it here until a use case becomes apparent. If such a use case does // arise, we most likely want to allow clients to pass in a function for validating the // azp claim rather than introducing logic that affects all clients of this library. // This naive implementation of the spec would almost certainly not be useful in practice: /*
        let azp_required = partially_verified_claims.audiences().len() > 1;

        // 5. If an azp (authorized party) Claim is present, the Client SHOULD verify that its
        //    client_id is the Claim Value.
        if let Some(authorized_party) = partially_verified_claims.authorized_party() {
            if *authorized_party != self.client_id {
                return Err(ClaimsVerificationError::InvalidAudience(format!(
                    "authorized party must match client ID `{}` (found `{}`",
                    *self.client_id, **authorized_party
                )));
            }
        } else if azp_required {
            return Err(ClaimsVerificationError::InvalidAudience(format!(
                "missing authorized party claim but multiple audiences found"
            )));
        }
        */ // Steps 6--8 are handled by the generic JwtClaimsVerifier. // 9. The current time MUST be before the time represented by the exp Claim. let cur_time = ( * self . time_fn ) ( ) ; if let Ok ( expiration ) = partially_verified_claims . expiration ( ) { if cur_time > expiration { return Err ( ClaimsVerificationError :: Expired ( format ! ( " " expiration cur_time ) ) ) ; } } else { return Err ( ClaimsVerificationError :: Other ( " " . to_string ( ) , ) ) ; } // 10. The iat Claim can be used to reject tokens that were issued too far away from the //     current time, limiting the amount of time that nonces need to be stored to prevent //     attacks. The acceptable range is Client specific. if let Ok ( ref issue_time ) = partially_verified_claims . issue_time ( ) { ( * self . iat_verifier_fn ) ( issue_time ) . map_err ( ClaimsVerificationError :: Expired ) ? ; } else { return Err ( ClaimsVerificationError :: Other ( " " . to_string ( ) , ) ) ; } // 11. If a nonce value was sent in the Authentication Request, a nonce Claim MUST be //     present and its value checked to verify that it is the same value as the one that was //     sent in the Authentication Request. The Client SHOULD check the nonce value for //     replay attacks. The precise method for detecting replay attacks is Client specific. if let Some ( expected_nonce ) = nonce { if let Some ( claims_nonce ) = partially_verified_claims . nonce ( ) { if claims_nonce != expected_nonce { return Err ( ClaimsVerificationError :: InvalidNonce ( " " . to_string ( ) , ) ) ; } } else { return Err ( ClaimsVerificationError :: InvalidNonce ( " " . to_string ( ) , ) ) ; } } // 12. If the acr Claim was requested, the Client SHOULD check that the asserted Claim Value //     is appropriate. The meaning and processing of acr Claim Values is out of scope for //     this specification. ( * self . acr_verifier_fn ) ( partially_verified_claims . auth_context_ref ( ) ) . map_err ( ClaimsVerificationError :: InvalidAuthContext ) ? ; // 13. If the auth_time Claim was requested, either through a specific request for this //     Claim or by using the max_age parameter, the Client SHOULD check the auth_time Claim //     value and request re-authentication if it determines too much time has elapsed since //     the last End-User authentication. match partially_verified_claims . auth_time ( ) { Some ( ref auth_time_result ) => auth_time_result . map ( | auth_time | ( * self . auth_time_verifier_fn ) ( Some ( & auth_time ) ) ) . map_err ( | _ | ClaimsVerificationError :: Other ( " " . to_string ( ) ) ) ? . map_err ( ClaimsVerificationError :: InvalidAuthTime ) ? , None => ( * self . auth_time_verifier_fn ) ( None ) . map_err ( ClaimsVerificationError :: InvalidAuthTime ) ? , } ; Ok ( partially_verified_claims ) }
TODO: Add a version that accepts a nonce validation function.
TODO : Add a version that accepts a nonce validation function .
&self
jwt
&'b JsonWebToken<
            IdTokenClaims<AC, GC>,
            JE,
            JS,
            JT,
            JsonWebTokenJsonPayloadDeserializer,
        >
nonce
Option<&Nonce>
&self
jwt
&'b JsonWebToken<
            IdTokenClaims<AC, GC>,
            JE,
            JS,
            JT,
            JsonWebTokenJsonPayloadDeserializer,
        >
nonce
Option<&Nonce>