Missing Authentication in Actix with Basic Auth
Missing Authentication in Actix with Basic Auth — how this specific combination creates or exposes the vulnerability
Missing Authentication in Actix when Basic Auth is configured but not enforced on sensitive endpoints allows unauthenticated attackers to access or manipulate protected resources. This specific combination becomes dangerous when routes are defined with Actix web utilities but the authentication guard is omitted, conditionally skipped, or applied only to a subset of handlers. Basic Auth relies on the client sending an Authorization header with base64-encoded credentials; if the application does not validate that header on every protected route, the credentials are effectively ignored.
In an Actix service, routes are composed using .route() or scoped methods, and authentication is commonly implemented as a wrapper or guard. If a developer creates a scope with .service() that includes both authenticated and unauthenticated handlers, or forgets to apply the authentication guard to a newly added endpoint, the endpoint becomes exposed. Because Actix does not implicitly enforce authentication across an entire scope, each handler must explicitly require authorization. An attacker can probe for these gaps by targeting endpoints that should be protected but lack the guard, revealing data or functionality that should require credentials.
middleBrick detects this category through unauthenticated scans that attempt to access sensitive endpoints without providing any Authorization header, as well as endpoints that accept Basic Auth credentials but do not enforce proper scope authorization. For example, an endpoint like /api/admin/users that should require valid credentials but lacks a guard will return a successful response when called without credentials, indicating a BOLA/IDOR or Authentication bypass. When combined with permissive CORS or route misconfiguration, missing authentication can allow lateral movement within the API. Remediation guidance emphasizes explicitly applying authentication guards to every sensitive handler, verifying that scopes and guards are consistently used, and testing both authenticated and unauthenticated paths to confirm enforcement.
Basic Auth-Specific Remediation in Actix — concrete code fixes
To remediate missing authentication in Actix with Basic Auth, ensure every sensitive handler or scope validates credentials before processing the request. Below are two concrete approaches: a per-handler guard and a scope-level wrapper. Always avoid conditionally applying guards and prefer centralized extraction to reduce mistakes.
Example 1: Per-handler authentication guard
This pattern attaches an authentication extractor directly to each handler that requires protection. It fails early if credentials are missing or invalid.
use actix_web::{web, HttpResponse, Result};
use actix_http::header::HeaderValue;
use base64::Engine;
async fn get_admin_data() -> Result<HttpResponse> {
// Handler logic for authenticated request
Ok(HttpResponse::Ok().body("Admin data"))
}
async fn auth_handler(
req: actix_web::HttpRequest,
) -> Result<actix_web::HttpResponse> {
// Extract Basic Auth header
let auth_header = req.headers().get("Authorization")
.ok_or_else(|| actix_web::error::ErrorUnauthorized("Missing Authorization header"))?;
let auth_str = auth_header.to_str()
.map_err(|_| actix_web::error::ErrorUnauthorized("Invalid header encoding"))?;
if !auth_str.starts_with("Basic ") {
return Err(actix_web::error::ErrorUnauthorized("Invalid auth type"));
}
let encoded = &auth_str[6..];
let decoded = base64::engine::general_purpose::STANDARD.decode(encoded)
.map_err(|_| actix_web::error::ErrorUnauthorized("Invalid base64"))?;
let creds = String::from_utf8(decoded)
.map_err(|_| actix_web::error::ErrorUnauthorized("Invalid credentials"))?;
let parts: Vec<&str> = creds.splitn(2, ':').collect();
if parts.len() != 2 || parts[0] != "admin" || parts[1] != "secret" {
return Err(actix_web::error::ErrorUnauthorized("Invalid credentials"));
}
get_admin_data().await
}
// Route definition requiring explicit guard
let cfg = web::resource("/api/admin/users")
.route(web::get().to(auth_handler));
Example 2: Scope-level wrapper using default services
Apply authentication to an entire scope so all services inherit the requirement, reducing the risk of forgetting a new endpoint.
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use actix_http::header::HeaderValue;
fn validate_basic(auth_header: &str) -> bool {
if !auth_header.starts_with("Basic ") {
return false;
}
let encoded = &auth_header[6..];
let decoded = base64::engine::general_purpose::STANDARD.decode(encoded).ok()?;
let creds = String::from_utf8(decoded).ok()?;
let parts: Vec<&str> = creds.splitn(2, ':').collect();
parts.get(0) == Some(&"admin") && parts.get(1) == Some(&"secret")
}
async fn admin_handler() -> impl Responder {
HttpResponse::Ok().body("Admin endpoint")
}
async fn public_handler() -> impl Responder {
HttpResponse::Ok().body("Public endpoint")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(
web::scope("/api")
.wrap_fn(|req, srv| {
let skip_auth = req.path() == "/api/public";
async move {
if !skip_auth {
let auth_header = req.headers().get("Authorization");
let ok = auth_header
.and_then(|h| h.to_str().ok())
.map_or(false, validate_basic);
if !ok {
return Ok(
HttpResponse::Unauthorized().finish().into(),
);
}
}
srv.call(req).await
}
})
.service(web::resource("/admin/users").to(admin_handler))
.service(web::resource("/public").to(public_handler)),
)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Key practices to avoid missing authentication: always attach a guard to sensitive routes, centralize credential extraction to reduce copy-paste errors, and verify that new endpoints explicitly include the guard. Use automated tests that call protected endpoints both with and without credentials to confirm enforcement. middleBrick complements these practices by scanning the unauthenticated attack surface and highlighting endpoints that lack required authentication, helping you catch configuration gaps before they are exploited.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |