use base64::engine::general_purpose::URL_SAFE_NO_PAD as BASE64_URL_SAFE_NO_PAD; use base64::Engine as _; use crate::utils::crypt_utils::sha256; /// Code challenge, as specified in /// /// See some implementation help in #[derive(Debug, Clone, Eq, PartialEq)] pub struct CodeChallenge { pub code_challenge: String, pub code_challenge_method: String, } impl CodeChallenge { pub fn verify_code(&self, code_verifer: &str) -> bool { match self.code_challenge_method.as_str() { "plain" => code_verifer.eq(&self.code_challenge), "S256" => { let encoded = BASE64_URL_SAFE_NO_PAD.encode(sha256(code_verifer.as_bytes())); encoded.eq(&self.code_challenge) } s => { log::error!("Unknown code challenge method: {}", s); false } } } } #[cfg(test)] mod test { use crate::data::code_challenge::CodeChallenge; #[test] fn test_plain() { let chal = CodeChallenge { code_challenge_method: "plain".to_string(), code_challenge: "text1".to_string(), }; assert_eq!(true, chal.verify_code("text1")); assert_eq!(false, chal.verify_code("text2")); } #[test] fn test_s256() { let chal = CodeChallenge { code_challenge_method: "S256".to_string(), code_challenge: "uSOvC48D8TMh6RgW-36XppMlMgys-6KAE_wEIev9W2g".to_string(), }; assert_eq!(true, chal.verify_code("HIwht3lCHfnsruA+7Sq8NP2mPj5cBZe0Ewf23eK9UQhK4TdCIt3SK7Fr/giCdnfjxYQILOPG2D562emggAa2lA==")); assert_eq!(false, chal.verify_code("text1")); } #[test] fn test_s256_2() { let chal = CodeChallenge { code_challenge_method: "S256".to_string(), code_challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM".to_string(), }; assert_eq!( true, chal.verify_code("dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk") ); assert_eq!(false, chal.verify_code("text1")); } }