use base64::Engine;
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use rand::RngExt;
use sha2::{Digest, Sha256};
const SECRET_BYTES: usize = 32;
fn generate_secret() -> String {
let bytes: [u8; SECRET_BYTES] = rand::rng().random();
URL_SAFE_NO_PAD.encode(bytes)
}
#[derive(Clone, Debug)]
pub struct Pkce {
verifier: String,
challenge: String,
}
impl Pkce {
pub fn generate() -> Self {
let verifier = generate_secret();
let challenge = Self::derive_challenge(&verifier);
Self {
verifier,
challenge,
}
}
pub fn derive_challenge(verifier: &str) -> String {
URL_SAFE_NO_PAD.encode(Sha256::digest(verifier.as_bytes()))
}
pub fn verifier(&self) -> &str {
&self.verifier
}
pub fn challenge(&self) -> &str {
&self.challenge
}
}
pub fn generate_state() -> String {
generate_secret()
}