use alibi_core::AuthResult;
use alibi_core::store::OAuthTokenKind;
use async_trait::async_trait;
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
use sha2::{Digest as _, Sha256};
#[async_trait]
pub trait OAuthTokenHasher: Send + Sync + std::fmt::Debug {
async fn hash(&self, token: &str, kind: &str) -> AuthResult<String>;
}
impl super::OAuthProviderPlugin {
fn token_prefix(&self, kind: OAuthTokenKind) -> &str {
match kind {
OAuthTokenKind::Access => self.config.opaque_access_token_prefix.as_deref(),
OAuthTokenKind::Refresh => self.config.refresh_token_prefix.as_deref(),
}
.unwrap_or_default()
}
pub(super) fn encode_token_prefix(&self, token: &str, kind: OAuthTokenKind) -> String {
format!("{}{token}", self.token_prefix(kind))
}
pub(super) fn decode_token_prefix<'a>(
&self,
token: &'a str,
kind: OAuthTokenKind,
) -> Option<&'a str> {
let prefix = self.token_prefix(kind);
if prefix.is_empty() {
Some(token)
} else {
token.strip_prefix(prefix)
}
}
pub async fn hash_token(&self, token: &str, kind: &str) -> AuthResult<String> {
if let Some(hasher) = &self.config.token_hasher {
hasher.hash(token, kind).await
} else {
Ok(URL_SAFE_NO_PAD.encode(Sha256::digest(token)))
}
}
}