tide_auth/
basic.rs

1use std::{borrow::Cow, str};
2
3use crate::{
4    traits::{AuthValue, Scheme, User},
5    Error,
6};
7use async_trait::async_trait;
8
9pub struct Basic {
10    basic: Option<Cow<'static, str>>,
11}
12
13unsafe impl Send for Basic {}
14
15unsafe impl Sync for Basic {}
16
17impl Default for Basic {
18    fn default() -> Self {
19        Basic { basic: None }
20    }
21}
22
23impl Basic {
24    pub fn new<T: Into<String>>(basic: T) -> Self {
25        let basic: String = basic.into();
26
27        Basic {
28            basic: Some(basic.into()),
29        }
30    }
31}
32
33#[async_trait]
34impl Scheme for Basic {
35    fn header_name() -> http_types::headers::HeaderName {
36        http_types::headers::AUTHORIZATION
37    }
38
39    async fn parse(
40        &self,
41        header_value: &http_types::headers::HeaderValue,
42    ) -> crate::Result<crate::traits::AuthValue> {
43        let basic = if let Some(ref basic) = self.basic {
44            basic.to_string()
45        } else {
46            "Basic".to_string()
47        };
48
49        if header_value.as_str().len() < basic.len() + 2 {
50            return Err(Error::Invalid);
51        }
52
53        let mut parts = header_value.as_str().splitn(2, ' ');
54
55        match parts.next() {
56            Some(scheme) if scheme == basic => {}
57            _ => return Err(Error::MissingScheme),
58        }
59        let inner_str = parts.next().ok_or(Error::Invalid)?;
60        let decode = base64::decode(inner_str)?;
61        let mut inner = str::from_utf8(&decode)?.splitn(2, ':');
62
63        let username = match inner.next() {
64            Some(username) => username,
65            _ => return Err(Error::MissingField("username")),
66        }
67        .to_string();
68        let password = match inner.next() {
69            Some(password) => password,
70            _ => return Err(Error::MissingField("password")),
71        }
72        .to_string();
73
74        Ok(AuthValue::Basic(User { username, password }))
75    }
76}