scylla/authentication/
mod.rs

1use async_trait::async_trait;
2use bytes::{BufMut, BytesMut};
3
4pub use crate::frame::Authenticator;
5
6/// Type to represent an authentication error message.
7pub type AuthError = String;
8
9/// Trait used to represent a user-defined custom authentication.
10#[async_trait]
11pub trait AuthenticatorSession: Send + Sync {
12    /// To handle an authentication challenge initiated by the server.
13    /// The information contained in the token parameter is authentication protocol specific.
14    /// It may be NULL or empty.
15    async fn evaluate_challenge(
16        &mut self,
17        token: Option<&[u8]>,
18    ) -> Result<Option<Vec<u8>>, AuthError>;
19
20    /// To handle the success phase of exchange.
21    /// The token parameters contain information that may be used to finalize the request.
22    async fn success(&mut self, token: Option<&[u8]>) -> Result<(), AuthError>;
23}
24
25/// Trait used to represent a factory of [`AuthenticatorSession`] instances.
26/// A new [`AuthenticatorSession`] instance will be created for each session.
27///
28/// The custom authenticator can be set using SessionBuilder::authenticator_provider method.  
29///
30/// Default: [`PlainTextAuthenticator`] is the default authenticator which requires username and
31/// password. It can be set by using SessionBuilder::user(\"user\", \"pass\") method.
32#[async_trait]
33pub trait AuthenticatorProvider: Sync + Send {
34    /// A pair of initial response and boxed [`AuthenticatorSession`]
35    /// should be returned if authentication is required by the server.
36    async fn start_authentication_session(
37        &self,
38        authenticator_name: &str,
39    ) -> Result<(Option<Vec<u8>>, Box<dyn AuthenticatorSession>), AuthError>;
40}
41
42struct PlainTextAuthenticatorSession;
43
44#[async_trait]
45impl AuthenticatorSession for PlainTextAuthenticatorSession {
46    async fn evaluate_challenge(
47        &mut self,
48        _token: Option<&[u8]>,
49    ) -> Result<Option<Vec<u8>>, AuthError> {
50        Err("Challenges are not expected during PlainTextAuthentication".to_string())
51    }
52
53    async fn success(&mut self, _token: Option<&[u8]>) -> Result<(), AuthError> {
54        Ok(())
55    }
56}
57
58/// Default authenticator provider that requires username and password if authentication is required.
59pub struct PlainTextAuthenticator {
60    username: String,
61    password: String,
62}
63
64impl PlainTextAuthenticator {
65    /// Creates new [`PlainTextAuthenticator`] instance with provided username and password.
66    pub fn new(username: String, password: String) -> Self {
67        PlainTextAuthenticator { username, password }
68    }
69}
70
71#[async_trait]
72impl AuthenticatorProvider for PlainTextAuthenticator {
73    async fn start_authentication_session(
74        &self,
75        _authenticator_name: &str,
76    ) -> Result<(Option<Vec<u8>>, Box<dyn AuthenticatorSession>), AuthError> {
77        let mut response = BytesMut::new();
78        let username_as_bytes = self.username.as_bytes();
79        let password_as_bytes = self.password.as_bytes();
80
81        response.put_u8(0);
82        response.put_slice(username_as_bytes);
83        response.put_u8(0);
84        response.put_slice(password_as_bytes);
85
86        Ok((
87            Some(response.to_vec()),
88            Box::new(PlainTextAuthenticatorSession),
89        ))
90    }
91}