diff options
author | Vika <vika@fireburn.ru> | 2022-09-20 00:26:04 +0300 |
---|---|---|
committer | Vika <vika@fireburn.ru> | 2022-09-20 00:26:04 +0300 |
commit | cfc12adcb8dc680e5fa105e38d79825fb91a3f3b (patch) | |
tree | a4e72ecf624c084b7ee3cd5fd9287fb057ddcaa4 | |
parent | 53c868691a09b84d71f724d23a09d1fb89368792 (diff) | |
download | kittybox-cfc12adcb8dc680e5fa105e38d79825fb91a3f3b.tar.zst |
kittybox-indieauth: fix extraneous padding in PKCE challenges
-rw-r--r-- | kittybox-rs/indieauth/src/lib.rs | 2 | ||||
-rw-r--r-- | kittybox-rs/indieauth/src/pkce.rs | 28 |
2 files changed, 25 insertions, 5 deletions
diff --git a/kittybox-rs/indieauth/src/lib.rs b/kittybox-rs/indieauth/src/lib.rs index 2cce1b9..752d9e9 100644 --- a/kittybox-rs/indieauth/src/lib.rs +++ b/kittybox-rs/indieauth/src/lib.rs @@ -285,7 +285,7 @@ impl AsRef<str> for State { /// client_id: "https://kittybox.fireburn.ru/companion/native".parse().unwrap(), /// redirect_uri: "https://kittybox.fireburn.ru/companion/native/redirect".parse().unwrap(), /// state: State::new(), -/// code_challenge: PKCEChallenge::new(verifier, PKCEMethod::default()), +/// code_challenge: PKCEChallenge::new(&verifier, PKCEMethod::default()), /// scope: Some(Scopes::new(vec![Scope::Create, Scope::Update, Scope::Delete, Scope::Media])), /// me: Some("https://fireburn.ru/".parse().unwrap()) /// }; diff --git a/kittybox-rs/indieauth/src/pkce.rs b/kittybox-rs/indieauth/src/pkce.rs index 511b9fc..bf8d1a0 100644 --- a/kittybox-rs/indieauth/src/pkce.rs +++ b/kittybox-rs/indieauth/src/pkce.rs @@ -68,13 +68,16 @@ pub struct PKCEChallenge { impl PKCEChallenge { /// Create a new challenge from a [PKCEVerifier] using a certain /// [PKCEMethod]. - pub fn new(code_verifier: PKCEVerifier, method: PKCEMethod) -> Self { + pub fn new(code_verifier: &PKCEVerifier, method: PKCEMethod) -> Self { Self { code_challenge: match method { PKCEMethod::S256 => { let mut hasher = Sha256::new(); hasher.update(code_verifier.as_ref()); - BASE64URL.encode(&hasher.finalize()) + let mut challenge = BASE64URL.encode(&hasher.finalize()); + challenge.retain(|c| c != '='); + + challenge }, PKCEMethod::Plain => code_verifier.to_string(), }, @@ -90,14 +93,14 @@ impl PKCEChallenge { /// use kittybox_indieauth::{PKCEVerifier, PKCEMethod, PKCEChallenge}; /// /// let verifier = PKCEVerifier::new(); - /// let challenge = PKCEChallenge::new(verifier.clone(), PKCEMethod::default()); + /// let challenge = PKCEChallenge::new(&verifier, PKCEMethod::default()); /// // Meanwhile, at the token endpoint, in the end of the ceremony... /// // ...the challenge gets retrieved from the stored data and verified /// assert!(challenge.verify(verifier)) /// ``` #[must_use] pub fn verify(&self, code_verifier: PKCEVerifier) -> bool { - Self::new(code_verifier, self.method) == *self + Self::new(&code_verifier, self.method) == *self } /// Return a reference to the code challenge string. @@ -110,3 +113,20 @@ impl PKCEChallenge { self.method } } + +#[cfg(test)] +mod tests { + use super::{PKCEMethod, PKCEVerifier, PKCEChallenge}; + + #[test] + /// A snapshot test generated using [Aaron Parecki's PKCE + /// tools](https://example-app.com/pkce) that checks for a + /// conforming challenge. + fn test_pkce_challenge_verification() { + let verifier = PKCEVerifier("ec03310e4e90f7bc988af05384060c3c1afeae4bb4d0f648c5c06b63".to_owned()); + + let challenge = PKCEChallenge::new(&verifier, PKCEMethod::S256); + + assert_eq!(challenge.as_str(), "aB8OG20Rh8UoQ9gFhI0YvPkx4dDW2MBspBKGXL6j6Wg"); + } +} |