pkce_std/
challenge.rs

1//! PKCE code challenges.
2//!
3//! [`Challenge`] is computed from the given string using the specified method:
4//!
5//! - [`Method::Plain`] uses the string as-is.
6//! - [`Method::Sha256`] hashes the string with SHA-256 and encodes the result.
7//!
8//! The string usually comes from the [`Verifier`], which creates the appropriate
9//! [`Challenge`] using the [`challenge`] method.
10//!
11//! [`challenge`]: Verifier::challenge
12
13use std::fmt;
14
15#[cfg(feature = "serde")]
16use serde::{Deserialize, Serialize};
17
18use crate::{encoding::encode, hash::sha256, method::Method, verifier::Verifier};
19
20/// Represents PKCE code challenges.
21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23pub struct Challenge {
24    secret: String,
25    method: Method,
26}
27
28/// Represents PKCE code challenge parts.
29pub type Parts = (String, Method);
30
31impl fmt::Display for Challenge {
32    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
33        self.secret().fmt(formatter)
34    }
35}
36
37impl Challenge {
38    /// Returns the borrowed secret.
39    pub const fn secret(&self) -> &str {
40        self.secret.as_str()
41    }
42
43    /// Returns the method used to generate the challenge.
44    pub const fn method(&self) -> Method {
45        self.method
46    }
47
48    /// Consumes [`Self`] and returns its `(secret, method)` parts.
49    pub fn into_parts(self) -> Parts {
50        (self.secret, self.method)
51    }
52}
53
54impl From<Challenge> for Parts {
55    fn from(challenge: Challenge) -> Self {
56        challenge.into_parts()
57    }
58}
59
60impl Challenge {
61    const fn new(secret: String, method: Method) -> Self {
62        Self { secret, method }
63    }
64}
65
66impl Challenge {
67    /// Creates code challenges from the given verifier using the given method.
68    pub fn create_using(method: Method, verifier: &Verifier<'_>) -> Self {
69        let string = verifier.get();
70
71        let secret = match method {
72            Method::Plain => string.to_owned(),
73            Method::Sha256 => encode(sha256(string)),
74        };
75
76        Self::new(secret, method)
77    }
78
79    /// Creates code challenges from the given verifier using the default method.
80    pub fn create(verifier: &Verifier<'_>) -> Self {
81        Self::create_using(Method::default(), verifier)
82    }
83}