about summary refs log tree commit diff
path: root/kittybox-rs/indieauth/src/pkce.rs
diff options
context:
space:
mode:
Diffstat (limited to 'kittybox-rs/indieauth/src/pkce.rs')
-rw-r--r--kittybox-rs/indieauth/src/pkce.rs28
1 files changed, 24 insertions, 4 deletions
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");
+    }
+}