Jwt Misconfiguration in Axum
How Jwt Misconfiguration Manifests in Axum
Jwt misconfiguration in Axum applications often stems from improper token validation, weak signing algorithms, or missing claims verification. These vulnerabilities can allow attackers to bypass authentication, escalate privileges, or access unauthorized resources.
A common misconfiguration occurs when developers use symmetric signing (HS256) in production instead of asymmetric (RS256). With HS256, anyone who knows the secret can forge tokens. Consider this vulnerable Axum middleware:
use jsonwebtoken::{encode, Header, EncodingKey};
use axum::middleware::Next;
use axum::http::{Request, Response};
async fn auth_middleware(req: Request, next: Next) -> Response {
let token = req.headers().get("Authorization")
.and_then(|h| h.to_str().ok())
.and_then(|h| h.strip_prefix("Bearer "))
.unwrap_or("");
let secret = "supersecretkey"; // HARDCODED SECRET
let token_data = jsonwebtoken::decode::(&token, &EncodingKey::from_secret(secret.as_bytes()), &[]);
match token_data {
Ok(_) => next.run(req).await,
Err(_) => Response::builder()
.status(401)
.body(axum::body::Body::empty())
.unwrap(),
}
}
This middleware has multiple critical flaws: the secret is hardcoded, HS256 is used instead of RS256, and there's no claims validation. An attacker who extracts the secret from source code can generate valid tokens for any user.
Another common issue is missing audience validation. Axum applications often validate tokens without checking the aud claim, allowing tokens issued for one service to be used on another:
let token_data = jsonwebtoken::decode::(&token, &EncodingKey::from_secret(secret.as_bytes()), &&[Algorithm::HS256]);
// Missing: validation of token_data.claims.aud against expected audience
Time-based attacks are also prevalent. Developers sometimes disable expiration validation or use weak clock tolerances:
// VULNERABLE: allows expired tokens
let validation = jsonwebtoken::Validation::new(Algorithm::HS256);
validation.validate_exp = false;
AXUM's extractors can introduce subtle vulnerabilities when combined with JWT middleware. A common pattern is extracting user data before authentication is fully validated:
async fn protected_route(
Extension(user): Extension<User>,
) -> &'static str {
// Assumes user is authenticated, but middleware might have failed silently
"Protected data"
}
Without proper error handling, this can return sensitive data even when token validation fails.
Axum-Specific Detection
Detecting JWT misconfigurations in Axum requires both static analysis and runtime scanning. middleBrick's black-box scanning approach is particularly effective for Axum applications since it tests the actual API endpoints without requiring source code access.
For Axum applications, middleBrick scans for several JWT-specific vulnerabilities:
Algorithm Confusion Attacks: The scanner tests if your endpoint accepts tokens with weaker algorithms than expected. It submits tokens signed with HS256 when RS256 is expected, attempting to forge valid tokens using the public key as a secret.
Missing Claims Validation: middleBrick verifies whether your Axum endpoints properly validate the aud (audience), iss (issuer), and sub (subject) claims. It crafts tokens with mismatched claims to test if they're accepted.
Weak Key Detection: The scanner analyzes token signatures to detect weak or predictable secrets. For HS256 tokens, it attempts to brute-force short secrets and identifies common weak keys like "secret", "password", or predictable patterns.
Time Validation Bypass: middleBrick tests whether expired tokens are accepted by submitting tokens with exp claims in the past and verifying if they're still processed.
To use middleBrick with your Axum API:
npx middlebrick scan https://yourapi.com/api/auth
The scanner tests all authentication endpoints and protected routes, providing a security score with specific findings. For CI/CD integration:
# GitHub Action example
- name: middleBrick API Security Scan
uses: middlebrick/middlebrick-action@v1
with:
url: https://yourapi.com
fail-on-score-below: 80
This configuration fails your build if the JWT security score drops below B grade, preventing vulnerable code from reaching production.
Axum-Specific Remediation
Securing JWT in Axum requires proper configuration and validation. Here's how to implement secure JWT handling in Axum applications:
Use Asymmetric Signing: Always prefer RS256 over HS256 in production:
use jsonwebtoken::{decode, DecodingKey, Validation};
use axum::middleware::Next;
use axum::http::{Request, Response};
use std::sync::Arc;
use std::fs;
// Load public key once at startup
let public_key_pem = fs::read_to_string("public_key.pem")?;
let decoding_key = DecodingKey::from_rsa_pem(public_key_pem.as_bytes())?;
async fn auth_middleware(req: Request, next: Next<B>) -> Response {
let token = req.headers().get("Authorization")
.and_then(|h| h.to_str().ok())
.and_then(|h| h.strip_prefix("Bearer "))
.unwrap_or("");
let validation = Validation::new(jsonwebtoken::Algorithm::RS256);
let token_data = decode::<Claims>(&token, &decoding_key, &validation);
match token_data {
Ok(claims) => {
// Validate claims
if claims.claims.aud != "your-api-audience" {
return Response::builder()
.status(401)
.body(axum::body::Body::empty())
.unwrap();
}
let mut req_with_claims = req.clone();
req_with_claims.extensions_mut().insert(claims);
next.run(req_with_claims).await
}
Err(_) => Response::builder()
.status(401)
.body(axum::body::Body::empty())
.unwrap(),
}
}
Implement Proper Claims Validation: Always validate all claims:
async fn validate_claims(claims: &Claims) -> Result<(), &'static str> {
// Validate issuer
if claims.iss != "expected-issuer" {
return Err("Invalid issuer");
}
// Validate audience
if !claims.aud.contains(&"your-api-audience".to_string()) {
return Err("Invalid audience");
}
// Validate subject
if claims.sub.is_empty() {
return Err("Missing subject");
}
Ok(())
}
Secure Token Extraction: Use Axum's typed headers for safer extraction:
use axum::extract::TypedHeader;
use axum::http::headers::authorization::Authorization;
use axum::http::headers::authorization::Bearer;
async fn auth_middleware(req: Request<B>, next: Next<B>) -> Response {
let TypedHeader(Authorization(Bearer { token })) =
TypedHeader::Add Rate Limiting: Protect against brute-force attacks:
use axum::middleware::Next;
use tower_crate::rate_limit;
use tower_crate::rate_limit::RateLimitLayer;
let rate_limit_layer = RateLimitLayer::new(
100, // requests
std::time::Duration::from_secs(60), // per minute
);
let app = axum::Router::new()
.route(...)
.layer(rate_limit_layer);
Secure Claims Structure: Define claims with proper validation:
use serde::{Deserialize, Serialize};
use jsonwebtoken::Algorithm;
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
aud: Vec<String>, // Validate against multiple audiences
iss: String,
exp: usize,
iat: usize,
#[serde(default)]
roles: Vec<String>,
}
impl Claims {
fn has_role(&self, role: &str) -> bool {
self.roles.contains(&role.to_string())
}
}
Testing JWT Security: Use middleBrick in your development workflow to catch misconfigurations before production:
// Test with middleBrick before deployment
npx middlebrick scan https://staging.yourapp.com/api
// Check for specific JWT findings
// Look for: algorithm confusion, weak keys, missing claims validation
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 |
Frequently Asked Questions
Why should I use RS256 instead of HS256 for JWT in Axum?
How can I test my Axum API's JWT security without source code access?
npx middlebrick scan https://yourapi.com and it will provide a security score with specific findings about your JWT implementation.