Files
tuliprox/backend/auth/src/auth_basic.rs
T

59 lines
1.9 KiB
Rust
Raw Normal View History

2026-08-27 18:36:23 +05:00
use crate::Rejection;
use axum::{
extract::FromRequestParts,
2026-08-29 15:32:08 +02:00
http::{header::AUTHORIZATION, request::Parts},
2026-08-27 18:36:23 +05:00
};
use base64::{engine::general_purpose, Engine};
2026-08-29 15:32:08 +02:00
use tuliprox_core::model::{AuthRejection, AuthScheme};
2025-04-23 20:20:14 +02:00
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct AuthBasic(pub (String, String));
impl<B> FromRequestParts<B> for AuthBasic
where
B: Send + Sync,
{
type Rejection = Rejection;
2026-06-15 14:09:31 +02:00
fn from_request_parts(
req: &mut Parts,
_: &B,
) -> impl std::future::Future<Output = Result<Self, Self::Rejection>> + Send {
std::future::ready(Self::decode_request_parts(req))
2025-04-23 20:20:14 +02:00
}
}
impl AuthBasic {
2026-08-27 18:36:23 +05:00
fn from_header(contents: (String, String)) -> Self { Self(contents) }
2025-04-23 20:20:14 +02:00
fn decode_request_parts(req: &mut Parts) -> Result<Self, Rejection> {
let authorization = req
.headers
2026-08-29 15:32:08 +02:00
.get(AUTHORIZATION)
.ok_or(AuthRejection::MissingHeader(AuthScheme::Basic))?
2025-04-23 20:20:14 +02:00
.to_str()
2026-08-29 15:32:08 +02:00
.map_err(|_| AuthRejection::MalformedHeader(AuthScheme::Basic))?;
2025-04-23 20:20:14 +02:00
2026-08-29 15:32:08 +02:00
match authorization.split_once(' ') {
Some((scheme, contents)) if scheme.eq_ignore_ascii_case("Basic") => {
2026-08-29 15:32:08 +02:00
Ok(Self::from_header(decode(contents)?))
2026-08-27 18:36:23 +05:00
}
2026-08-29 15:32:08 +02:00
_ => Err(AuthRejection::WrongScheme(AuthScheme::Basic)),
2025-04-23 20:20:14 +02:00
}
}
}
/// Decodes the two parts of basic auth using the colon
fn decode(input: &str) -> Result<(String, String), Rejection> {
// Decode from base64 into a string
2026-08-29 15:32:08 +02:00
let decoded =
general_purpose::STANDARD.decode(input).map_err(|_| AuthRejection::MalformedHeader(AuthScheme::Basic))?;
let decoded = String::from_utf8(decoded).map_err(|_| AuthRejection::MalformedHeader(AuthScheme::Basic))?;
2025-04-23 20:20:14 +02:00
// Return depending on if password is present
2026-08-29 15:32:08 +02:00
decoded
.split_once(':')
.map(|(username, password)| (username.trim().to_string(), password.trim().to_string()))
.ok_or(AuthRejection::MissingBasicPassword)
2026-06-15 14:09:31 +02:00
}