aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/auth.rs64
-rw-r--r--src/errors.rs13
-rw-r--r--src/main.rs10
3 files changed, 26 insertions, 61 deletions
diff --git a/src/auth.rs b/src/auth.rs
index 82b407c..b4717d1 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -1,8 +1,7 @@
-use actix_web::dev::{Service, ServiceRequest, ServiceResponse};
-use actix_web::{HttpRequest, ResponseError};
-use futures::future::Either;
+use actix_web::dev::ServiceRequest;
+use actix_web::HttpMessage;
+use actix_web_httpauth::extractors::basic::BasicAuth;
use sha2::{Digest, Sha256, Sha512};
-use std::future::{ready, Future};
use crate::errors::ContextualError;
@@ -13,16 +12,12 @@ pub struct BasicAuthParams {
pub password: String,
}
-impl BasicAuthParams {
- fn try_from_request(req: &HttpRequest) -> actix_web::Result<Self> {
- use actix_web::http::header::Header;
- use actix_web_httpauth::headers::authorization::{Authorization, Basic};
-
- let auth = Authorization::<Basic>::parse(req)?.into_scheme();
- Ok(Self {
+impl From<BasicAuth> for BasicAuthParams {
+ fn from(auth: BasicAuth) -> Self {
+ Self {
username: auth.user_id().to_string(),
password: auth.password().unwrap_or(&"".into()).to_string(),
- })
+ }
}
}
@@ -74,47 +69,24 @@ pub fn get_hash<T: Digest>(text: &str) -> Vec<u8> {
hasher.update(text);
hasher.finalize().to_vec()
}
+
pub struct CurrentUser {
pub name: String,
}
-fn handle_auth(req: &HttpRequest) -> Result<(), ContextualError> {
+pub async fn handle_auth(
+ req: ServiceRequest,
+ cred: BasicAuth,
+) -> actix_web::Result<ServiceRequest> {
let required_auth = &req.app_data::<crate::MiniserveConfig>().unwrap().auth;
- if required_auth.is_empty() {
- // auth is disabled by configuration
- return Ok(());
- }
-
- match BasicAuthParams::try_from_request(req) {
- Ok(cred) => match match_auth(&cred, required_auth) {
- true => {
- req.extensions_mut().insert(CurrentUser {
- name: cred.username,
- });
- Ok(())
- }
- false => Err(ContextualError::InvalidHttpCredentials),
- },
- Err(_) => Err(ContextualError::RequireHttpCredentials),
- }
-}
+ req.extensions_mut().insert(CurrentUser {
+ name: cred.user_id().to_string(),
+ });
-pub fn auth_middleware<S>(
- mut req: ServiceRequest,
- srv: &S,
-) -> impl Future<Output = actix_web::Result<ServiceResponse>> + 'static
-where
- S: Service<ServiceRequest, Response = ServiceResponse, Error = actix_web::Error>,
- S::Future: 'static,
-{
- match handle_auth(req.parts_mut().0) {
- Ok(_) => Either::Left(srv.call(req)),
- Err(err) => {
- let resp = req.into_response(err.error_response());
- Either::Right(ready(Ok(resp)))
- }
- }
+ match_auth(&cred.into(), required_auth)
+ .then(|| req)
+ .ok_or_else(|| ContextualError::InvalidHttpCredentials.into())
}
#[rustfmt::skip]
diff --git a/src/errors.rs b/src/errors.rs
index 25d0529..c6fcce3 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -58,10 +58,6 @@ pub enum ContextualError {
#[error("{0}")]
ArchiveCreationDetailError(String),
- /// Might occur when the HTTP credentials are not provided
- #[error("Access requires HTTP authentication")]
- RequireHttpCredentials,
-
/// Might occur when the HTTP credentials are not correct
#[error("Invalid credentials for HTTP authentication")]
InvalidHttpCredentials,
@@ -90,20 +86,17 @@ impl ResponseError for ContextualError {
Self::ArchiveCreationError(_, err) => err.status_code(),
Self::RouteNotFoundError(_) => StatusCode::NOT_FOUND,
Self::InsufficientPermissionsError(_) => StatusCode::FORBIDDEN,
- Self::InvalidHttpCredentials | Self::RequireHttpCredentials => StatusCode::UNAUTHORIZED,
+ Self::InvalidHttpCredentials => StatusCode::UNAUTHORIZED,
Self::InvalidHttpRequestError(_) => StatusCode::BAD_REQUEST,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}
fn error_response(&self) -> HttpResponse {
- if let Self::RequireHttpCredentials = self {
- } else {
- log_error_chain(self.to_string());
- }
+ log_error_chain(self.to_string());
let mut resp = HttpResponse::build(self.status_code());
- if let Self::RequireHttpCredentials | Self::InvalidHttpCredentials = self {
+ if let Self::InvalidHttpCredentials = self {
resp.append_header((
header::WWW_AUTHENTICATE,
header::HeaderValue::from_static("Basic realm=\"miniserve\""),
diff --git a/src/main.rs b/src/main.rs
index 133f320..cb11145 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,6 +7,7 @@ use std::time::Duration;
use actix_web::web;
use actix_web::{http::header::ContentType, Responder};
use actix_web::{middleware, App, HttpRequest, HttpResponse};
+use actix_web_httpauth::middleware::HttpAuthentication;
use anyhow::{bail, Result};
use clap::{crate_version, Clap, IntoApp};
use clap_generate::generators::{Bash, Elvish, Fish, PowerShell, Zsh};
@@ -211,11 +212,10 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), ContextualError> {
.route(&format!("/{}", inside_config.css_route), web::get().to(css))
.service(
web::scope(inside_config.random_route.as_deref().unwrap_or(""))
- // we should use `actix_web_httpauth::middleware::HttpAuthentication`
- // but it is unfortuantrly broken
- // see: https://github.com/actix/actix-extras/issues/127
- // TODO replace this when fixed upstream
- .wrap_fn(auth::auth_middleware)
+ .wrap(middleware::Condition::new(
+ !inside_config.auth.is_empty(),
+ HttpAuthentication::basic(auth::handle_auth),
+ ))
.configure(|c| configure_app(c, &inside_config)),
)
.default_service(web::get().to(error_404))