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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//! Implementation of http basic authentication
//!
//! See [AuthBasic] for the most commonly-used data structure
use crate::;
use FromRequestParts;
use ;
use ;
/// Basic authentication extractor, containing an identifier as well as an optional password
///
/// This is enabled via the `auth-basic` feature
///
/// # Example
///
/// Though this structure can be used like any other axum extractor, we recommend this pattern:
///
/// ```no_run
/// use axum_auth::AuthBasic;
///
/// /// Takes basic auth details and shows a message
/// async fn handler(AuthBasic((id, password)): AuthBasic) -> String {
/// if let Some(password) = password {
/// format!("User '{}' with password '{}'", id, password)
/// } else {
/// format!("User '{}' without password", id)
/// }
/// }
/// ```
///
/// # Errors
///
/// There are a few errors which this extractor can make. By default, all invalid responses are `400 BAD REQUEST` with one of these messages:
///
/// - \`Authorization\` header could not be decoded – The header couldn't be decoded, probably missing a colon
/// - \`Authorization\` header must be for basic authentication – Someone tried to use bearer auth instead of basic auth
/// - \`Authorization\` header is missing – The header was required but it wasn't found
/// - \`Authorization\` header contains invalid characters – The header couldn't be processed because of invalid characters
);
/// Custom extractor trait for basic auth allowing you to implement custom responses
///
/// This is enabled via the `auth-basic` feature
///
/// # Usage
///
/// To create your own basic auth extractor using this create, you have to:
///
/// 1. Make the extractor struct, something like `struct Example((String, Option<String>));`
/// 2. Implement [FromRequestParts] that links to step 3, copy and paste this from the example below
/// 3. Implement [AuthBasicCustom] to generate your extractor with your custom options, see the example below
///
/// Once you've completed these steps, you should have a new extractor which is just as easy to use as [AuthBasic] but has all of your custom configuration options inside of it!
///
/// # Example
///
/// This is what a typical custom extractor should look like in full, copy-paste this and edit it:
///
/// ```rust
/// use axum_auth::{AuthBasicCustom, Rejection};
/// use http::{request::Parts, StatusCode};
/// use axum::extract::FromRequestParts;
///
/// /// Your custom basic auth returning a fun 418 for errors
/// struct MyCustomBasicAuth((String, Option<String>));
///
/// // This is where you define your custom options:
/// impl AuthBasicCustom for MyCustomBasicAuth {
/// const ERROR_CODE: StatusCode = StatusCode::IM_A_TEAPOT; // <-- define custom status code here
/// const ERROR_OVERWRITE: Option<&'static str> = None; // <-- define overwriting message here
///
/// fn from_header(contents: (String, Option<String>)) -> Self {
/// Self(contents)
/// }
/// }
///
/// // This is just boilerplate for now, copy and paste this:
/// impl<B> FromRequestParts<B> for MyCustomBasicAuth
/// where
/// B: Send + Sync,
/// {
/// type Rejection = Rejection;
///
/// async fn from_request_parts(parts: &mut Parts, _: &B) -> Result<Self, Self::Rejection> {
/// Self::decode_request_parts(parts)
/// }
/// }
/// ```
///
/// Some notes about this example for some more insight:
///
/// - There's no reason for the [FromRequestParts] to ever change out of this pattern unless you're doing something special
/// - It's recommended to use the `struct BasicExample((String, Option<String>));` pattern because it makes using it from routes easy
/// Decodes the two parts of basic auth using the colon