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
use crate::error::AuthBasicError;
#[derive(Debug, PartialEq)]
pub struct Credentials {
pub user_id: String,
pub password: String,
}
impl Credentials {
pub fn new(user_id: &str, password: &str) -> Self {
Self {
user_id: user_id.to_string(),
password: password.to_string(),
}
}
pub fn decode(auth_header_value: String) -> Result<Self, AuthBasicError> {
let decoded = base64::decode(auth_header_value)?;
let as_utf8 = String::from_utf8(decoded)?;
let parts = as_utf8.split(':');
let mut parts: Vec<String> = parts.map(|p| p.to_string()).collect();
if parts.len() > 2 {
parts = vec![parts[0].clone(), parts[1..].join(":")];
}
if parts.len() == 2 {
let credentials = Credentials {
user_id: parts.get(0).unwrap().to_string(),
password: parts.get(1).unwrap().to_string(),
};
return Ok(credentials);
}
Err(AuthBasicError::InvalidAuthorizationHeader)
}
pub fn encode(&self) -> String {
let credentials = format!("{}:{}", self.user_id, self.password);
base64::encode(credentials.as_bytes())
}
pub fn from_header(auth_header: String) -> Result<Credentials, AuthBasicError> {
let parts = auth_header.split(' ');
let parts: Vec<String> = parts.map(|part| part.to_string()).collect();
if parts.len() > 2 {
return Err(AuthBasicError::InvalidAuthorizationHeader);
}
if let Some(auth_type) = parts.get(0) {
if auth_type.to_lowercase() != "basic" {
return Err(AuthBasicError::InvalidScheme(auth_type.to_string()));
}
}
if let Some(encoded_credentials) = parts.get(1) {
let credentials = Credentials::decode(encoded_credentials.clone())?;
return Ok(credentials);
}
Err(AuthBasicError::InvalidAuthorizationHeader)
}
pub fn as_http_header(&self) -> String {
let as_base64 = self.encode();
format!("Basic {}", as_base64)
}
}