use async_trait::async_trait;
use bytes::{BufMut, BytesMut};
pub use crate::frame::Authenticator;
pub type AuthError = String;
#[async_trait]
pub trait AuthenticatorSession: Send + Sync {
async fn evaluate_challenge(
&mut self,
token: Option<&[u8]>,
) -> Result<Option<Vec<u8>>, AuthError>;
async fn success(&mut self, token: Option<&[u8]>) -> Result<(), AuthError>;
}
#[async_trait]
pub trait AuthenticatorProvider: Sync + Send {
async fn start_authentication_session(
&self,
authenticator_name: &str,
) -> Result<(Option<Vec<u8>>, Box<dyn AuthenticatorSession>), AuthError>;
}
struct PlainTextAuthenticatorSession;
#[async_trait]
impl AuthenticatorSession for PlainTextAuthenticatorSession {
async fn evaluate_challenge(
&mut self,
_token: Option<&[u8]>,
) -> Result<Option<Vec<u8>>, AuthError> {
Err("Challenges are not expected during PlainTextAuthentication".to_string())
}
async fn success(&mut self, _token: Option<&[u8]>) -> Result<(), AuthError> {
Ok(())
}
}
pub struct PlainTextAuthenticator {
username: String,
password: String,
}
impl PlainTextAuthenticator {
pub fn new(username: String, password: String) -> Self {
PlainTextAuthenticator { username, password }
}
}
#[async_trait]
impl AuthenticatorProvider for PlainTextAuthenticator {
async fn start_authentication_session(
&self,
_authenticator_name: &str,
) -> Result<(Option<Vec<u8>>, Box<dyn AuthenticatorSession>), AuthError> {
let mut response = BytesMut::new();
let username_as_bytes = self.username.as_bytes();
let password_as_bytes = self.password.as_bytes();
response.put_u8(0);
response.put_slice(username_as_bytes);
response.put_u8(0);
response.put_slice(password_as_bytes);
Ok((
Some(response.to_vec()),
Box::new(PlainTextAuthenticatorSession),
))
}
}