Token Leakage in Axum with Basic Auth
Token Leakage in Axum with Basic Auth — how this specific combination creates or exposes the vulnerability
Token leakage in an Axum service using HTTP Basic Authentication occurs when credentials or derived tokens are unintentionally exposed in logs, error messages, URLs, or browser history. Basic Auth sends credentials as a base64-encoded string in the Authorization header; while not plaintext, it is easily reversible and must always be transmitted over TLS to prevent interception. If an Axum application mishandles the decoded credentials—such as logging the header value directly or embedding it into redirect URLs—sensitive information can be exposed to attackers with access to logs or network traces.
Common leakage vectors include verbose error reporting that echoes the Authorization header, server configurations that log full request headers, and client-side behavior such as browser password saving or referrer headers that expose credentials to third-party sites. In microservice architectures where Axum services call one another, passing Basic Auth credentials in URLs or headers without strict validation can lead to token leakage across services. Additionally, if session tokens or API keys are derived from Basic Auth credentials without proper key derivation, those tokens might be predictable or persist beyond the intended scope, increasing the risk of unauthorized access.
An attacker who gains access to logs or can intercept traffic might use leaked credentials to impersonate users or pivot to internal systems. Because Basic Auth does not inherently provide replay protection, captured credentials can be reused unless additional protections such as nonce or timestamp validation are implemented at the application layer. MiddleBrick scans can detect patterns indicative of token leakage by correlating unauthenticated endpoint testing with data exposure checks, helping identify endpoints where credentials are improperly handled.
Basic Auth-Specific Remediation in Axum — concrete code fixes
To mitigate token leakage in Axum, ensure credentials are never logged, avoid exposing them in URLs, and always enforce HTTPS. Use middleware to strip or mask sensitive headers before logging and validate that error responses do not include stack traces or raw request data. Implement secure credential parsing and avoid deriving tokens in a reversible manner.
Secure Basic Auth parsing in Axum
The following Axum handler demonstrates safe extraction and validation of Basic Auth credentials without logging sensitive values:
use axum::{
async_trait,
extract::{self, Request},
response::Response,
routing::get,
Router,
};
use base64::prelude::*;
use http::{Request as HttpRequest, StatusCode};
use std::net::SocketAddr;
use tower_http::services::ServeDir;
struct AuthExtractor;
#[async_trait]
extract::FromRequest for AuthExtractor {
type Rejection = Response;
async fn from_request(req: Request, _: &mut extract::State) -> Result {
let auth_header = req.headers().get("authorization");
let header_value = match auth_header {
Some(v) => v.to_str().map_err(|_| (StatusCode::UNAUTHORIZED, "Invalid header"))?,
None => return Err((StatusCode::UNAUTHORIZED, "Missing authorization header").into()),
};
if !header_value.starts_with("Basic ") {
return Err((StatusCode::UNAUTHORIZED, "Unsupported authentication scheme").into());
}
let encoded = header_value.trim_start_matches("Basic ");
let decoded = BASE64_STANDARD.decode(encoded).map_err(|_| (StatusCode::UNAUTHORIZED, "Invalid encoding"))?;
let credentials = String::from_utf8(decoded).map_err(|_| (StatusCode::UNAUTHORIZED, "Invalid credentials"))?;
// Split only on the first colon to allow passwords containing colons
let mut parts = credentials.splitn(2, ':');
let user = parts.next().ok_or_else(|| (StatusCode::UNAUTHORIZED, "Missing username"))?;
let pass = parts.next().ok_or_else(|| (StatusCode::UNAUTHORIZED, "Missing password"))?;
// Perform constant-time validation in real applications
if user == "admin" && pass == "correct-hashed-derived-value" {
Ok(AuthExtractor)
} else {
Err((StatusCode::UNAUTHORIZED, "Invalid credentials").into())
}
}
}
async fn protected_route() -> &'static str {
"Access granted"
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/api/secure", get(protected_route))
.layer(extract::tower_layer(AuthExtractor));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
tracing::debug!(listening = %addr, "Server started");
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
Operational and configuration safeguards
- Always serve APIs over TLS to prevent credential interception in transit.
- Configure your logging framework to filter or redact the Authorization header. For example, in tracing-based Rust applications, avoid logging the full request headers and instead log only metadata such as route and method.
- Do not embed Basic Auth credentials in URLs or query parameters, as these are more likely to be stored in browser history, proxy logs, or server logs.
- Implement rate limiting and account lockout mechanisms to reduce the impact of credential brute-forcing.
- Consider migrating from Basic Auth to token-based mechanisms (e.g., OAuth 2.0 or session cookies with secure flags) where feasible to reduce long-term leakage risks.
MiddleBrick’s scans can validate that your endpoints enforce TLS and do not expose credentials in responses or logs, providing prioritized findings and remediation guidance aligned with frameworks such as OWASP API Top 10.