use crate::{config::HttpBasicAuthConfig, error::ServiceError, FilterRequest, FilterResponseOut}; use base64::Engine; use http_body_util::{combinators::BoxBody, BodyExt}; use hyper::{ header::{HeaderValue, AUTHORIZATION, WWW_AUTHENTICATE}, Response, StatusCode, }; use log::debug; use std::ops::ControlFlow; pub fn http_basic( config: &HttpBasicAuthConfig, req: &FilterRequest, resp: &mut FilterResponseOut, ) -> Result, ServiceError> { if let Some(auth) = req.headers().get(AUTHORIZATION) { let k = auth .as_bytes() .strip_prefix(b"Basic ") .ok_or(ServiceError::BadAuth)?; let k = base64::engine::general_purpose::STANDARD.decode(k)?; let k = String::from_utf8(k)?; if config.valid.contains(&k) { debug!("valid auth"); return Ok(ControlFlow::Continue(())); } else { debug!("invalid auth"); } } debug!("unauthorized; sending auth challenge"); let mut r = Response::new(BoxBody::<_, ServiceError>::new( String::new().map_err(|_| unreachable!()), )); *r.status_mut() = StatusCode::UNAUTHORIZED; r.headers_mut().insert( WWW_AUTHENTICATE, HeaderValue::from_str(&format!("Basic realm=\"{}\"", config.realm)).unwrap(), ); *resp = Some(r); Ok(ControlFlow::Break(())) }