1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//! A default implementation of a authentication extractor for basic authentication.

use actix_web::http::{header, HeaderMap, HeaderValue};
use async_trait::async_trait;

use crate::authentication::error::error_type::AuthenticationError;
use crate::authentication::scheme::authentication::Authentication;
use crate::authentication::scheme::basic::BasicAuthentication;
use crate::authentication::scheme::header_extractor::{
    extract_auth_header, AuthorizationHeaderExtractor,
};

/// The definition of a `BasicAuthenticationExtractor`. The authentication extractor
/// extracts the authentication information from the authorization header and decodes
/// the user credentials to be used in the user authentication.
#[derive(Clone)]
pub struct BasicAuthenticationExtractor {}

impl BasicAuthenticationExtractor {
    /// Constructs a new instance of `BasicAuthenticationExtractor`.
    pub fn new() -> BasicAuthenticationExtractor {
        BasicAuthenticationExtractor {}
    }

    fn extract_basic(
        &self,
        header: &HeaderValue,
    ) -> Result<BasicAuthentication, AuthenticationError> {
        let token = extract_auth_header(header, "Basic", 7)?;

        // Decode the token
        if let Ok(decoded) = base64::decode(token) {
            let decoded_str = std::str::from_utf8(&decoded);
            if let Ok(credentials_str) = decoded_str {
                let mut credentials = credentials_str.splitn(2, ':');

                let username = credentials
                    .next()
                    .ok_or(AuthenticationError::InvalidAuthorizationHeader)?
                    .to_string();

                let password = credentials
                    .next()
                    .ok_or(AuthenticationError::InvalidAuthorizationHeader)?
                    .to_string();

                return Ok(BasicAuthentication { username, password });
            }
        }

        Err(AuthenticationError::InvalidAuthorizationHeader)
    }
}

impl Default for BasicAuthenticationExtractor {
    fn default() -> Self {
        Self::new()
    }
}

#[async_trait]
impl AuthorizationHeaderExtractor for BasicAuthenticationExtractor {
    async fn extract_token(
        &self,
        headers: &HeaderMap,
    ) -> Result<Box<dyn Authentication>, AuthenticationError> {
        let authorization_header = headers.get(header::AUTHORIZATION);
        let header_value =
            authorization_header.ok_or(AuthenticationError::AuthorizationHeaderNotSet)?;
        Ok(Box::new(self.extract_basic(header_value)?))
    }
}