HIGH missing authenticationactix

Missing Authentication in Actix

How Missing Authentication Manifests in Actix

Missing authentication in Actix applications typically occurs through route handler oversights and middleware configuration gaps. The most common pattern involves unprotected endpoints that should require authentication, often due to developers forgetting to apply authentication middleware to specific routes or API versions.

A critical vulnerability pattern in Actix is the accidental exposure of administrative endpoints. Consider this problematic structure:

async fn admin_dashboard() -> impl Responder {
    // Sensitive admin operations
    HttpResponse::Ok().body("Admin dashboard")
}

async fn public_api() -> impl Responder {
    // Public endpoint
    HttpResponse::Ok().body("Public API")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(
                web::resource("/admin").route(web::get().to(admin_dashboard))
            )
            .service(
                web::resource("/api").route(web::get().to(public_api))
            )
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

This code exposes the admin dashboard without any authentication checks. Attackers can directly access sensitive functionality by sending requests to /admin.

Another Actix-specific manifestation involves improper middleware ordering. Authentication middleware must be registered before route registration:

App::new()
    // WRONG: routes registered before middleware
    .service(web::resource("/api").route(web::get().to(public_api)))
    .wrap(AuthenticationMiddleware::new())
    .service(web::resource("/admin").route(web::get().to(admin_dashboard))) // Still unprotected

The correct pattern ensures middleware wraps all subsequent routes:

App::new()
    .wrap(AuthenticationMiddleware::new())
    .service(web::resource("/api").route(web::get().to(public_api)))
    .service(web::resource("/admin").route(web::get().to(admin_dashboard))) // Now protected

Route-specific authentication bypasses also occur when developers use .default_service() without proper guards, creating catch-all routes that bypass authentication checks.

Actix-Specific Detection

Detecting missing authentication in Actix applications requires both static analysis and runtime scanning. Static analysis involves examining route definitions and middleware configuration patterns.

Using middleBrick's CLI for Actix API scanning:

npx middlebrick scan https://your-actix-api.com

middleBrick automatically tests unauthenticated access to endpoints, identifying those that should require authentication but don't. The scanner tests for:

  • Administrative endpoints accessible without credentials
  • Database modification operations without authentication
  • User management functions exposed publicly
  • Configuration endpoints that should be protected
  • Payment processing operations without authentication

For OpenAPI specification analysis, middleBrick resolves $ref references and cross-references endpoint definitions with actual runtime behavior:

middlebrick scan --spec openapi.json https://your-actix-api.com

This detects discrepancies between documented security requirements and actual implementation.

Manual detection techniques for Actix include:

// Check for missing .wrap() calls
App::new()
    .service(web::resource("/users").route(web::get().to(get_users))) // Missing auth wrapper
    .service(web::resource("/posts").route(web::post().to(create_post))) // Missing auth wrapper

Look for route handlers that perform sensitive operations without authentication guards. Common indicators include database writes, file operations, or administrative functions without preceding authentication checks.

Actix-Specific Remediation

Actix provides several authentication middleware options. The most common approach uses actix-web-httpauth for basic and bearer token authentication:

use actix_web_httpauth::middleware::HttpAuthentication;
use actix_web_httpauth::extractors::basic::BasicAuth;

async fn validate_credentials(auth: BasicAuth) -> Result<(), actix_web_httpauth::Error> {
    let creds = auth.credentials();
    if creds.username == "admin" && creds.password == "secret" {
        Ok(())
    } else {
        Err(actix_web_httpauth::Error::new(401))
    }
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let auth = HttpAuthentication::basic(validate_credentials);
    
    HttpServer::new(|| {
        App::new()
            .wrap(auth)
            .service(web::resource("/admin").route(web::get().to(admin_dashboard)))
            .service(web::resource("/api").route(web::get().to(public_api)))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

For JWT-based authentication, use jsonwebtoken with custom middleware:

use jsonwebtoken::{decode, DecodingKey, Validation};

struct JwtAuthMiddleware;

#[async_trait::async_trait]
impl actix_web::middleware::Transform for JwtAuthMiddleware {
    type Request = actix_web::dev::ServiceRequest;
    type Response = actix_web::dev::ServiceResponse;
    type Error = actix_web::Error;
    type InitError = ();
    type Transform = JwtAuthMiddlewareService;
    
    async fn new_transform(&self) -> Result<Self::Transform, Self::InitError> {
        Ok(JwtAuthMiddlewareService)
    }
}

struct JwtAuthMiddlewareService;

#[async_trait::async_trait]
impl actix_web::dev::Transform for JwtAuthMiddlewareService {
    type Request = actix_web::dev::ServiceRequest;
    type Response = actix_web::dev::ServiceResponse;
    type Error = actix_web::Error;
    type Future = actix_web::dev::Ready<Result<Self::Response, Self::Error>>;
    
    async fn call(&mut self, req: Self::Request, srv: &mut actix_web::dev::Service) -> Self::Future {
        if let Some(auth) = req.headers().get("Authorization") {
            if let Ok(token) = auth.to_str() {
                if token.starts_with("Bearer ") {
                    let token = &token[7..];
                    if let Ok(_) = decode::<()>(&token, &DecodingKey::from_secret("secret".as_bytes()), &Validation::new(jsonwebtoken::Algorithm::HS256)) {
                        return actix_web::dev::ready(srv.call(req).await);
                    }
                }
            }
        }
        actix_web::dev::ready(Err(actix_web::error::ErrorUnauthorized("Unauthorized")))
    }
}

For route-specific authentication, use guard to protect individual endpoints:

use actix_web::guard;

async fn protected_route() -> impl Responder {
    HttpResponse::Ok().body("Protected content")
}

async fn public_route() -> impl Responder {
    HttpResponse::Ok().body("Public content")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(web::resource("/public").route(web::get().to(public_route)))
            .service(web::resource("/protected")
                .guard(guard::fn_guard(|req| {
                    req.headers().contains_key("Authorization")
                }))
                .route(web::get().to(protected_route)))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Best practices include implementing authentication at the application level and using route guards for exceptions, never the reverse.

Related CWEs: authentication

CWE IDNameSeverity
CWE-287Improper Authentication CRITICAL
CWE-306Missing Authentication for Critical Function CRITICAL
CWE-307Brute Force HIGH
CWE-308Single-Factor Authentication MEDIUM
CWE-309Use of Password System for Primary Authentication MEDIUM
CWE-347Improper Verification of Cryptographic Signature HIGH
CWE-384Session Fixation HIGH
CWE-521Weak Password Requirements MEDIUM
CWE-613Insufficient Session Expiration MEDIUM
CWE-640Weak Password Recovery HIGH

Frequently Asked Questions

How can I test if my Actix API has missing authentication vulnerabilities?
Use middleBrick's self-service scanner by running npx middlebrick scan https://your-actix-api.com. It tests unauthenticated access to all endpoints and identifies those that should require authentication but don't. The scanner also analyzes your OpenAPI spec if provided, detecting discrepancies between documented security requirements and actual implementation.
What's the difference between middleware-based and guard-based authentication in Actix?
Middleware-based authentication (using .wrap()) applies to all routes below it in the chain, making it ideal for application-wide protection. Guard-based authentication (using guard::fn_guard()) applies to specific routes only, useful for protecting individual endpoints while leaving others public. Middleware is generally more maintainable for comprehensive protection.