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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
//! Authenticate the request with basic auth.
//!
//! ### Configuration
//!
//!| key | alias | Description | Default Value | Possible Values |
//!| -------- | ---------- | -------------------------------------------- | ------------- | --------------- |
//!| type | - | Required in order to use this authentication | `basic` | `basic` |
//!| username | user / usr | Username to use for the authentification | `null` | String |
//!| password | pass / pwd | Password to use for the authentification | `null` | String |
//!
//! ### Examples
//!
//!```json
//![
//! {
//! "type": "read",
//! "connector":{
//! "type": "curl",
//! "endpoint": "{{ CURL_ENDPOINT }}",
//! "path": "/get",
//! "method": "get",
//! "authenticator": {
//! "type": "basic",
//! "username": "{{ BASIC_USERNAME }}",
//! "password": "{{ BASIC_PASSWORD }}",
//! }
//! },
//! }
//!]
//!```
use crate::helper::string::{DisplayOnlyForDebugging, Obfuscate};
use super::Authenticator;
use async_trait::async_trait;
use base64::Engine;
use serde::{Deserialize, Serialize};
use std::{
fmt,
io::{Error, ErrorKind, Result},
};
use surf::http::headers;
#[derive(Deserialize, Serialize, Clone)]
#[serde(default, deny_unknown_fields)]
pub struct Basic {
#[serde(alias = "usr")]
#[serde(alias = "user")]
pub username: String,
#[serde(alias = "pwd")]
#[serde(alias = "pass")]
pub password: String,
}
impl Default for Basic {
fn default() -> Self {
Basic {
username: "".to_owned(),
password: "".to_owned(),
}
}
}
impl fmt::Debug for Basic {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Basic")
.field("username", &self.username)
.field(
"password",
&self
.password
.to_owned()
.to_obfuscate()
.display_only_for_debugging(),
)
.finish()
}
}
impl Basic {
/// Get new authentification
///
/// # Examples
///
/// ```no_run
/// use chewdata::connector::authenticator::basic::Basic;
///
/// let auth = Basic::new("my_username", "my_password");
/// ```
pub fn new(username: &str, password: &str) -> Self {
Basic {
username: username.to_string(),
password: password.to_string(),
}
}
}
#[async_trait]
impl Authenticator for Basic {
/// See [`Authenticator::authenticate`] for more details.
///
/// # Examples
///
/// ```no_run
/// use chewdata::connector::authenticator::{AuthenticatorType, basic::Basic, Authenticator};
/// use async_std::prelude::*;
/// use std::io;
/// use base64::Engine;
///
/// #[async_std::main]
/// async fn main() -> io::Result<()> {
/// let username = "my_username";
/// let password = "my_password";
/// let token_expected = "Basic bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=";
///
/// let (auth_name, auth_value) = Basic::new(username, password).authenticate().await?;
/// assert_eq!(auth_name, "authorization".to_string().into_bytes());
/// assert_eq!(token_expected.as_bytes(), auth_value);
///
/// Ok(())
/// }
/// ```
async fn authenticate(&self) -> Result<(Vec<u8>, Vec<u8>)> {
if let ("", "") = (self.username.as_ref(), self.password.as_ref()) {
return Err(Error::new(
ErrorKind::InvalidData,
"Basic authentification require a username and a password",
));
}
let basic = base64::engine::general_purpose::STANDARD
.encode(format!("{}:{}", self.username, self.password));
Ok((
headers::AUTHORIZATION.as_str().as_bytes().to_vec(),
format!("Basic {}", basic).as_bytes().to_vec(),
))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[async_std::test]
async fn authenticate() {
let username = "my_username";
let password = "my_password";
let token_expected = "Basic bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=";
let (auth_name, auth_value) = Basic::new(username, password).authenticate().await.unwrap();
assert_eq!(auth_name, "authorization".to_string().into_bytes());
assert_eq!(token_expected.as_bytes(), auth_value);
}
}