37 lines
1.1 KiB
Rust
37 lines
1.1 KiB
Rust
![]() |
use base64::{engine::general_purpose::URL_SAFE as base64url, Engine};
|
||
|
use serde::{Serialize, Deserialize};
|
||
|
use tetratto_shared::hash::hash;
|
||
|
use super::{Result, Error};
|
||
|
|
||
|
#[derive(Serialize, Deserialize, PartialEq, Eq)]
|
||
|
pub enum PkceChallengeMethod {
|
||
|
S256,
|
||
|
}
|
||
|
|
||
|
#[derive(Serialize, Deserialize, PartialEq, Eq)]
|
||
|
pub enum AppScope {
|
||
|
#[serde(alias = "user-read-profile")]
|
||
|
UserReadProfile,
|
||
|
}
|
||
|
|
||
|
/// Check a verifier against the stored challenge (using the given [`PkceChallengeMethod`]).
|
||
|
pub fn check_verifier(verifier: &str, challenge: &str, method: PkceChallengeMethod) -> Result<()> {
|
||
|
if method != PkceChallengeMethod::S256 {
|
||
|
return Err(Error::MiscError("only S256 is supported".to_string()));
|
||
|
}
|
||
|
|
||
|
let decoded = match base64url.decode(challenge.as_bytes()) {
|
||
|
Ok(hash) => hash,
|
||
|
Err(e) => return Err(Error::MiscError(e.to_string())),
|
||
|
};
|
||
|
|
||
|
let hash = hash(verifier.to_string());
|
||
|
|
||
|
if hash.as_bytes() != decoded {
|
||
|
// the verifier we received does not match the verifier from the stored challenge
|
||
|
return Err(Error::NotAllowed);
|
||
|
}
|
||
|
|
||
|
Ok(())
|
||
|
}
|