aboutsummaryrefslogtreecommitdiffstats
path: root/src/auth.rs
diff options
context:
space:
mode:
authorkhai96_ <hvksmr1996@gmail.com>2019-05-17 07:11:38 +0000
committerkhai96_ <hvksmr1996@gmail.com>2019-05-17 07:11:38 +0000
commita77c71dde6a480c8c6a096b7cacd03de63a5ee6b (patch)
tree41709cb3662e07031cf318cb64404ea2d645bf92 /src/auth.rs
parentUpdate unit tests (diff)
parentMerge pull request #116 from svenstaro/dependabot/cargo/reqwest-0.9.17 (diff)
downloadminiserve-a77c71dde6a480c8c6a096b7cacd03de63a5ee6b.tar.gz
miniserve-a77c71dde6a480c8c6a096b7cacd03de63a5ee6b.zip
Merge remote-tracking branch 'mainrepo/master' into multiple-auths-alt
Diffstat (limited to 'src/auth.rs')
-rw-r--r--src/auth.rs87
1 files changed, 70 insertions, 17 deletions
diff --git a/src/auth.rs b/src/auth.rs
index da5f4a9..3828265 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -1,9 +1,10 @@
-use actix_web::http::header;
+use actix_web::http::{header, StatusCode};
use actix_web::middleware::{Middleware, Response};
use actix_web::{HttpRequest, HttpResponse, Result};
use sha2::{Digest, Sha256, Sha512};
-use crate::errors::{ContextualError};
+use crate::errors::{self, ContextualError};
+use crate::renderer;
pub struct Auth;
@@ -36,10 +37,7 @@ pub fn parse_basic_auth(
let basic_removed = authorization_header
.to_str()
.map_err(|e| {
- ContextualError::ParseError(
- "HTTP authentication header".to_string(),
- e.to_string(),
- )
+ ContextualError::ParseError("HTTP authentication header".to_string(), e.to_string())
})?
.replace("Basic ", "");
let decoded = base64::decode(&basic_removed).map_err(ContextualError::Base64DecodeError)?;
@@ -109,7 +107,14 @@ impl Middleware<crate::MiniserveConfig> for Auth {
Err(err) => {
let auth_err = ContextualError::HTTPAuthenticationError(Box::new(err));
return Ok(Response::Done(
- HttpResponse::BadRequest().body(auth_err.to_string()),
+ HttpResponse::BadRequest().body(
+ build_unauthorized_response(
+ &req,
+ auth_err,
+ true,
+ StatusCode::BAD_REQUEST,
+ ),
+ ),
));
}
};
@@ -118,20 +123,68 @@ impl Middleware<crate::MiniserveConfig> for Auth {
return Ok(Response::Done(resp));
}
- let new_resp = HttpResponse::Unauthorized().finish();
- return Ok(Response::Done(new_resp));
+ return Ok(Response::Done(
+ HttpResponse::Unauthorized().body(
+ build_unauthorized_response(
+ &req,
+ ContextualError::InvalidHTTPCredentials,
+ true,
+ StatusCode::UNAUTHORIZED,
+ )
+ )
+ ));
}
- let new_resp = HttpResponse::Unauthorized()
- .header(
- header::WWW_AUTHENTICATE,
- header::HeaderValue::from_static("Basic realm=\"miniserve\""),
- )
- .finish();
- Ok(Response::Done(new_resp))
+ Ok(Response::Done(
+ HttpResponse::Unauthorized()
+ .header(
+ header::WWW_AUTHENTICATE,
+ header::HeaderValue::from_static("Basic realm=\"miniserve\""),
+ )
+ .body(build_unauthorized_response(
+ &req,
+ ContextualError::InvalidHTTPCredentials,
+ true,
+ StatusCode::UNAUTHORIZED,
+ ))
+ ))
}
}
+/// Builds the unauthorized response body
+/// The reason why log_error_chain is optional is to handle cases where the auth pop-up appears and when the user clicks Cancel.
+/// In those case, we do not log the error to the terminal since it does not really matter.
+fn build_unauthorized_response(
+ req: &HttpRequest<crate::MiniserveConfig>,
+ error: ContextualError,
+ log_error_chain: bool,
+ error_code: StatusCode,
+) -> String {
+ let error = ContextualError::HTTPAuthenticationError(Box::new(error));
+
+ if log_error_chain {
+ errors::log_error_chain(error.to_string());
+ }
+ let return_path = match &req.state().random_route {
+ Some(random_route) => format!("/{}", random_route),
+ None => "/".to_string(),
+ };
+
+ renderer::render_error(
+ &error.to_string(),
+ error_code,
+ &return_path,
+ None,
+ None,
+ req.state().default_color_scheme,
+ req.state().default_color_scheme,
+ false,
+ false,
+ )
+ .into_string()
+}
+
+#[rustfmt::skip]
#[cfg(test)]
mod tests {
use super::*;
@@ -182,7 +235,7 @@ mod tests {
case(true, "obi", "hello there", "obi", "hello there", "sha256"),
case(false, "obi", "hello there", "obi", "hi!", "sha256"),
case(true, "obi", "hello there", "obi", "hello there", "sha512"),
- case(false, "obi", "hello there", "obi", "hi!", "sha512"),
+ case(false, "obi", "hello there", "obi", "hi!", "sha512")
)]
fn test_single_auth(
should_pass: bool,