use async_trait::async_trait;
use rusmes_proto::Username;
use std::sync::Arc;
pub mod backends;
pub mod file;
pub mod sasl;
pub mod security;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScramCredentials {
pub salt: Vec<u8>,
pub iteration_count: u32,
pub stored_key: Vec<u8>,
pub server_key: Vec<u8>,
}
pub enum AuthBackendKind {
File(FileBackendConfig),
Sql(backends::sql::SqlConfig),
Ldap(backends::ldap::LdapConfig),
OAuth2(backends::oauth2::OAuth2Config),
}
#[derive(Debug, Clone, Default)]
pub struct FileBackendConfig {
pub path: String,
pub hash_algorithm: file::HashAlgorithm,
}
impl AuthBackendKind {
pub async fn build(self) -> anyhow::Result<Arc<dyn AuthBackend>> {
match self {
AuthBackendKind::File(cfg) => {
let backend =
file::FileAuthBackend::with_algorithm(&cfg.path, cfg.hash_algorithm).await?;
Ok(Arc::new(backend))
}
AuthBackendKind::Sql(cfg) => {
let backend = backends::sql::SqlBackend::new(cfg).await?;
Ok(Arc::new(backend))
}
AuthBackendKind::Ldap(cfg) => {
let backend = backends::ldap::LdapBackend::new(cfg);
Ok(Arc::new(backend))
}
AuthBackendKind::OAuth2(cfg) => {
let backend = backends::oauth2::OAuth2Backend::new(cfg);
Ok(Arc::new(backend))
}
}
}
}
#[async_trait]
pub trait AuthBackend: Send + Sync {
async fn authenticate(&self, username: &Username, password: &str) -> anyhow::Result<bool>;
async fn verify_identity(&self, username: &Username) -> anyhow::Result<bool>;
async fn list_users(&self) -> anyhow::Result<Vec<Username>>;
async fn create_user(&self, username: &Username, password: &str) -> anyhow::Result<()>;
async fn delete_user(&self, username: &Username) -> anyhow::Result<()>;
async fn change_password(&self, username: &Username, new_password: &str) -> anyhow::Result<()>;
async fn fetch_scram_credentials(
&self,
_user: &str,
) -> anyhow::Result<Option<ScramCredentials>> {
Ok(None)
}
async fn get_scram_params(&self, _username: &str) -> anyhow::Result<(Vec<u8>, u32)> {
Err(anyhow::anyhow!(
"SCRAM-SHA-256 credential storage not implemented in this AuthBackend"
))
}
async fn get_scram_stored_key(&self, _username: &str) -> anyhow::Result<Vec<u8>> {
Err(anyhow::anyhow!(
"SCRAM-SHA-256 credential storage not implemented in this AuthBackend"
))
}
async fn get_scram_server_key(&self, _username: &str) -> anyhow::Result<Vec<u8>> {
Err(anyhow::anyhow!(
"SCRAM-SHA-256 credential storage not implemented in this AuthBackend"
))
}
async fn store_scram_credentials(
&self,
_username: &Username,
_salt: Vec<u8>,
_iterations: u32,
_stored_key: Vec<u8>,
_server_key: Vec<u8>,
) -> anyhow::Result<()> {
Err(anyhow::anyhow!(
"SCRAM-SHA-256 credential storage not implemented in this AuthBackend"
))
}
async fn get_apop_secret(&self, _username: &Username) -> anyhow::Result<String> {
Err(anyhow::anyhow!(
"APOP authentication not supported by this AuthBackend"
))
}
async fn verify_bearer_token(&self, token: &str) -> anyhow::Result<Username> {
let _ = token;
Err(anyhow::anyhow!(
"Bearer token authentication is not supported by this AuthBackend"
))
}
}