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
//! Handles parsing the `Authorization` header.
use base64::prelude::*;
/// Authorization header.
#[derive(Debug, PartialEq)]
pub enum Authorization {
/// HTTP Basic authentication.
///
/// Basic auth uses a username and password. It's not very secure,
/// but it's good enough to protect against random visitors.
Basic { user: String, password: String },
/// See [`crate::controller::auth::Token`].
Token { token: String },
/// Bearer authentication. Token validation is up to the caller.
Bearer { token: String },
}
impl Authorization {
/// Parse the `Authorization` header value.
///
/// # Example
///
/// ```
/// # use rwf::http::Authorization;
/// let auth = Authorization::parse("Basic YWxpY2U6d29uZGVybGFuZA==");
///
/// assert_eq!(auth, Some(Authorization::Basic {
/// user: "alice".into(),
/// password: "wonderland".into(),
/// }));
/// ```
pub fn parse(header: &str) -> Option<Authorization> {
let mut parts = header.split(" ");
match parts.next() {
Some(ident) => match ident {
"Basic" => match parts.next() {
Some(auth) => Self::basic(auth),
None => None,
},
"Bearer" => match parts.next() {
Some(auth) => Some(Authorization::Bearer {
token: auth.to_owned(),
}),
None => None,
},
"Token" => match parts.next() {
Some(auth) => Some(Authorization::Token {
token: auth.to_owned(),
}),
None => None,
},
_ => None,
},
None => None,
}
}
fn basic(value: &str) -> Option<Authorization> {
if let Ok(decoded) = BASE64_STANDARD.decode(value.as_bytes()) {
let decoded = String::from_utf8_lossy(&decoded);
let mut parts = decoded.split(":");
if let Some(user) = parts.next() {
if let Some(password) = parts.next() {
return Some(Authorization::Basic {
user: user.to_owned(),
password: password.to_owned(),
});
}
}
}
None
}
}