Missing Authentication in Axum with Jwt Tokens
Missing Authentication in Axum with Jwt Tokens — how this specific combination creates or exposes the vulnerability
In Axum, a common misconfiguration with JWT tokens is relying on the presence of a token in the Authorization header without enforcing validation on every protected route. When routes intended to be protected do not explicitly require a verified principal, the endpoint becomes unauthenticated from a security perspective. middleBrick flags this as Missing Authentication because the API accepts requests without a valid, verified JWT, effectively exposing functionality that should be restricted.
JWT tokens must be validated for each request: signature, issuer, audience, expiration, and relevant scopes or claims. If any of these checks are omitted or bypassed—such as not attaching an authorization extractor to the router, failing to call a verification function before handler execution, or incorrectly marking a route as optional—then an attacker can call the endpoint with a missing, malformed, or unsigned token and still receive a response. This is distinct from authentication bypass via invalid credentials; here the API does not require authentication at all for that route.
Real-world examples include routes that omit a layer requiring a verified identity or that conditionally call a verification function only when a custom header is present. Another common pattern is using optional extractors (e.g., Option) and then proceeding without checking validity, which results in unauthenticated access. Because JWT validation is asynchronous and involves cryptographic checks, failing to await or propagate errors can also lead to treating a missing or invalid token as acceptable.
middleBrick’s unauthenticated attack surface testing will attempt calls without tokens, with empty tokens, and with obviously invalid tokens to determine whether endpoints respond as if authentication is required. Findings include endpoints that return data or perform actions without a valid JWT, which commonly maps to OWASP API Top 10:2023 — API1:2023 Broken Object Level Authorization when combined with other issues, and can facilitate BOLA/IDOR if object references are exposed without ownership checks.
Because Axum does not enforce authentication by default, developers must explicitly wire JWT validation into the application’s routing and extractors. Missing this wiring consistently across the codebase leads to endpoints that are unintentionally public. Continuous scanning and route inventory are essential to ensure every sensitive route requires a verified JWT and that no legacy or generated routes fall outside the protection boundary.
Jwt Tokens-Specific Remediation in Axum — concrete code fixes
Remediation centers on consistently validating JWT tokens on every protected route and ensuring that invalid or missing tokens result in rejection before reaching business logic. Use tower-rs based extractors and middleware to centralize validation and avoid route-level omissions.
Example: Define a JWT validation extractor that returns a verified identity or fails with an appropriate rejection. Then require that extractor on all routes that must be authenticated.
use axum::{routing::get, Router};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
exp: usize,
iss: String,
aud: String,
}
async fn validate_jwt(token: &str) -> Result {
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = true;
validation.set_issuer(&["my-issuer"]);
validation.set_audience(&["my-audience"]);
let token_data = decode::(
token,
&DecodingKey::from_secret("your-secret".as_ref()),
&validation,
)?;
Ok(token_data.claims)
}
async fn protected_handler(claims: Claims) -> String {
format!("Hello, user: {}", claims.sub)
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route(
"/protected",
get(axum_extra::extract::cookie::CookieJar::>::extract()
.map_err(|err| match err {
JsonWebTokenError::Missing => (StatusCode::UNAUTHORIZED, "missing token"),
JsonWebTokenError::InvalidToken { .. } => (StatusCode::UNAUTHORIZED, "invalid token"),
_ => (StatusCode::INTERNAL_SERVER_ERROR, "internal error"),
})
.and_then(|jwt| async move {
validate_jwt(&jwt.claims().token)
.await
.map_err(|_| (StatusCode::UNAUTHORIZED, "invalid claims"))
})
.map(Into::into))
)
.route("/public", get(|| async { "public" }));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
In this example, the /protected route requires a valid JWT with correct issuer, audience, and expiration; any missing or invalid token results in a 401 response before the handler runs. The /public route remains intentionally open, demonstrating explicit opt-in for authentication.
For larger applications, centralize validation with middleware or a request guard that checks a verified identity in extensions. This ensures every route that should require authentication is checked consistently and that developers cannot accidentally omit validation when adding new endpoints.
middleBrick’s scans will verify that protected endpoints reject unauthenticated requests and that JWT validation logic is invoked on the server side. Remediation guidance will highlight routes with Missing Authentication and provide code-level patterns to enforce token validation, including proper error handling for expired or malformed tokens.
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 |