aboutsummaryrefslogtreecommitdiff
path: root/src/filters/auth.rs
blob: 92a9ba38662c861314a94af755f2a315901d89c3 (plain)
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
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<ControlFlow<()>, 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(()))
}