diff --git a/crates/data-model/src/oauth2/authorization_grant.rs b/crates/data-model/src/oauth2/authorization_grant.rs index c53ce9ea..4b73cb51 100644 --- a/crates/data-model/src/oauth2/authorization_grant.rs +++ b/crates/data-model/src/oauth2/authorization_grant.rs @@ -24,7 +24,7 @@ use url::Url; use super::{client::Client, session::Session}; use crate::{traits::StorageBackend, StorageBackendMarker}; -#[derive(Debug, Error)] +#[derive(Debug, Error, PartialEq)] pub enum PkceVerificationError { #[error("code_verifier should be at least 43 characters long")] TooShort, @@ -63,7 +63,7 @@ impl Pkce { return Err(PkceVerificationError::TooLong); } - if verifier + if !verifier .chars() .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '.' || c == '_' || c == '~') { @@ -238,3 +238,42 @@ impl AuthorizationGrant { self.created_at - Duration::seconds(max_age.unwrap_or(3600 * 24 * 365)) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_pkce_verification() { + // This challenge is taken from the RFC7636 appendices + let pkce = Pkce::new( + PkceCodeChallengeMethod::S256, + "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM".to_string(), + ); + + assert_eq!( + pkce.verify("dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"), + Ok(()), + ); + + assert_eq!( + pkce.verify("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"), + Err(PkceVerificationError::VerificationFailed), + ); + + assert_eq!( + pkce.verify("tooshort"), + Err(PkceVerificationError::TooShort), + ); + + assert_eq!( + pkce.verify("toolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolongtoolong"), + Err(PkceVerificationError::TooLong), + ); + + assert_eq!( + pkce.verify("this is long enough but has invalid characters in it"), + Err(PkceVerificationError::InvalidCharacters), + ); + } +}