Missing Authentication in Axum
How Missing Authentication Manifests in Axum
Missing authentication in Axum applications creates critical security vulnerabilities where unauthorized users can access sensitive API endpoints without any form of identity verification. This manifests through several Axum-specific patterns that developers often overlook.
The most common manifestation occurs when route handlers are defined without any authentication middleware. Consider this vulnerable Axum endpoint:
use axum::{routing::get, Router};
async fn get_user_profile(user_id: String) -> String {
// No authentication check
format!("User profile for {}", user_id)
}
let app = Router::new()
.route("/api/users/:user_id/profile", get(get_user_profile));
This endpoint exposes user profile data to anyone who knows the URL structure. An attacker can enumerate user IDs and harvest sensitive information without any authentication challenge.
Another critical pattern involves missing authentication on administrative endpoints. Many Axum applications expose management interfaces like:
async fn admin_dashboard() -> String {
// Administrative data exposed without auth
"Admin dashboard data".to_string()
}
let app = Router::new()
.route("/admin/dashboard", get(admin_dashboard));
Database endpoints without authentication create severe data exposure risks. Axum applications often expose CRUD operations directly:
async fn delete_user(user_id: String) -> String {
// No authentication, anyone can delete users
format!("Deleted user {}", user_id)
}
let app = Router::new()
.route("/api/users/:user_id", delete(delete_user));
Missing authentication also appears in middleware chains where authentication middleware is conditionally applied. A common anti-pattern:
let app = Router::new()
.route("/public/*", public_handler)
.route("/private/*", private_handler); // No auth middleware applied
State management without authentication creates another vulnerability vector. When Axum applications use shared state without access controls:
use axum::extract::State;
async fn get_user_settings(
State(app_state): State
) -> String {
// Accesses shared state without authentication
format!("Settings: {:?}", app_state.settings)
}
Missing authentication in Axum's extractors can lead to unauthorized access. When using custom extractors without authentication checks:
async fn process_payment(
Json(payment_data): Json
) -> String {
// Processes payments without verifying user identity
format!("Processing payment of ${}", payment_data.amount)
}
Axum-Specific Detection
Detecting missing authentication in Axum applications requires both static code analysis and runtime scanning approaches. middleBrick provides specialized detection for Axum-specific patterns.
Static detection focuses on identifying unprotected route handlers. middleBrick's analysis engine examines Axum route definitions and flags endpoints without authentication middleware. The scanner specifically looks for:
- Route handlers without
AuthMiddlewareor similar authentication layers - Administrative endpoints exposed without authorization checks
- Database CRUD operations without authentication guards
- State extraction patterns without identity verification
Runtime scanning with middleBrick tests the actual API surface by sending unauthenticated requests to all endpoints. For Axum applications, this reveals:
$ middlebrick scan https://api.example.com
╔──────────────────────────────────────────────────────────────────────┐
│ Missing Authentication (Critical) │
│ Authentication bypass allows unauthenticated access to │
│ sensitive endpoints. │
└──────────────────────────────────────────────────────────────────────┘
Endpoints affected:
├── GET /api/users/:id (BOLA vulnerability)
├── DELETE /api/admin/:resource (Missing auth)
└── POST /api/payments (No authentication)
middleBrick's OpenAPI analysis detects missing authentication by cross-referencing route definitions with authentication requirements specified in the API specification. When Axum applications provide OpenAPI specs:
use axum::http::StatusCode;
async fn get_protected_resource(
auth: Authorization
) -> Result<String, StatusCode> {
// Authentication required but may be missing in some routes
Ok("Protected data".to_string())
}
The scanner identifies discrepancies between documented authentication requirements and actual implementation, flagging endpoints that should require authentication but don't enforce it.
middleBrick's LLM security module also detects missing authentication in AI endpoints, which is particularly relevant for Axum applications using AI/ML features:
async fn ai_chatbot(
Json(prompt): Json
) -> String {
// No authentication for AI endpoint
chat_with_ai(prompt).await
}
This specialized detection ensures comprehensive coverage of authentication vulnerabilities across all Axum application types.
Axum-Specific Remediation
Remediating missing authentication in Axum requires implementing proper authentication middleware and ensuring consistent application across all sensitive endpoints. Here's how to secure Axum applications effectively.
The foundation is implementing a robust authentication middleware. Axum's middleware system provides clean integration:
use axum::{middleware::Next, response::IntoResponse, http::Request};
use tower_http::auth::RequireAuthorizationLayer;
use std::sync::Arc;
// Create authentication middleware
let auth_layer = RequireAuthorizationLayer::basic(|user, pass| {
user == "admin" && pass == "secret"
});
// Apply middleware to entire app
let app = Router::new()
.route(...)
.layer(auth_layer);
For more sophisticated authentication, implement custom middleware that integrates with your auth system:
use axum::{middleware::Next, response::IntoResponse, http::{Request, Response}};
use tower::ServiceExt;
use serde_json::json;
use std::sync::Arc;
async fn auth_middleware(
req: Request,
next: Next,
) -> Result<impl IntoResponse, (http::StatusCode, String)> {
// Extract auth token from headers
let auth_header = req.headers().get("Authorization");
match auth_header {
Some(auth) if is_valid_token(auth) => {
next.run(req).await
}
_ => {
let error = json!({
"error": "Authentication required",
"status": 401
});
Err((http::StatusCode::UNAUTHORIZED, error.to_string()))
}
}
}
fn is_valid_token(auth: &HeaderValue) -> bool {
// Implement your token validation logic
// This could check JWT, API keys, session tokens, etc.
true // Replace with actual validation
}
Apply authentication selectively using route groups and middleware:
use axum::{routing::get, Router, Json};
// Public routes (no auth required)
let public_routes = Router::new()
.route("/api/public/health", get(health_check))
.route("/api/public/docs", get(api_docs));
// Private routes (require authentication)
let private_routes = Router::new()
.route("/api/users/:id", get(get_user))
.route("/api/admin/*", get(admin_dashboard))
.layer(auth_middleware_layer());
let app = Router::new()
.nest("/api/public", public_routes)
.nest("/api", private_routes);
For database operations, ensure authentication before any data manipulation:
async fn delete_user(
Path(user_id): Path<String>,
auth: Authorization<Bearer>,
db: Data<PgPool>
) -> Result<Json<DeleteResponse>, StatusCode> {
// Verify user has permission to delete
if !has_delete_permission(&auth.0, &user_id).await? {
return Err(StatusCode::FORBIDDEN);
}
sqlx::query("DELETE FROM users WHERE id = $1")
.bind(user_id)
.execute(db)
.await?;
Ok(Json(DeleteResponse { success: true }))
}
State management requires authentication checks before accessing shared resources:
use axum::extract::State;
async fn get_user_settings(
State(app_state): State<AppState>,
auth: Authorization<Bearer>
) -> Result<Json<UserSettings>, StatusCode> {
let user_id = extract_user_id_from_token(&auth.0)?;
let settings = app_state.settings.get(&user_id)
.ok_or(StatusCode::NOT_FOUND)?;
Ok(Json(settings.clone()))
}
For AI endpoints, implement authentication to prevent unauthorized access to LLM APIs:
async fn ai_chatbot(
Json(prompt): Json<String>,
auth: Authorization<Bearer>
) -> Result<Json<AIResponse>, StatusCode> {
// Authenticate before processing AI request
let user = validate_ai_access(&auth.0)?;
let response = chat_with_ai(prompt, user).await;
Ok(Json(response))
}
Finally, implement comprehensive testing to ensure authentication is properly enforced:
#[cfg(test)]
mod tests {
use axum::http::StatusCode;
#[tokio::test]
async fn test_auth_required() {
let client = setup_test_client();
// Test unauthenticated access
let res = client.get("/api/users/123").send().await;
assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
// Test authenticated access
let res = client.get("/api/users/123")
.header("Authorization", "Bearer valid_token")
.send().await;
assert_eq!(res.status(), StatusCode::OK);
}
}
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 |