Session Fixation in Axum with Api Keys
Session Fixation in Axum with Api Keys — how this specific combination creates or exposes the vulnerability
Session fixation occurs when an application assigns a user a session identifier before authentication and fails to rotate that identifier after login. In Axum, this risk is amplified when API keys are used for authentication but session management is still relied upon for authorization or state tracking. Axum is a Rust web framework, and while it does not manage sessions by default, developers commonly integrate session layers via crates such as axum-sessions or tower-sessions. If an API key is accepted both before and after authentication without forcing a new session or token binding, an attacker can fixate a session by persuading a victim to authenticate using a known key.
Consider a scenario where an API key is passed in an Authorization: ApiKey <key> header and also used to look up a session store key stored in a cookie. Because the session ID remains unchanged across authentication, an attacker who knows the session ID (e.g., via logs, referrer headers, or insecure client storage) can reuse it post-authentication. This maps directly to the OWASP API Top 10 A07:2021 — Identification and Authentication Failures, and mirrors classic session fixation patterns seen in traditional web apps, but now applied to key-based flows. In an unauthenticated scan, middleBrick tests for BOLA/IDOR and Authentication weaknesses; in this context, it can detect whether session identifiers remain stable across auth transitions when API keys are involved.
Furthermore, if the API key is stored in local storage or exposed in client-side code, the combination of a fixed session and a persistable key increases data exposure risk. An attacker who steals the key might reuse the fixed session to maintain access even after password or key rotation. middleBrick’s LLM/AI Security checks do not apply here, but its Authentication and BOLA/IDOR tests can surface cases where endpoints accept the same key both pre- and post-login without invalidating the prior session context. Real-world analogs include misconfigured services where JWTs or opaque tokens are reused without proper binding to a per-session nonce or key rotation, echoing CVE patterns seen in improperly designed API gateways.
Api Keys-Specific Remediation in Axum — concrete code fixes
Remediation focuses on ensuring session or token state changes immediately after successful authentication, and that API keys are treated as credentials rather than session anchors. In Axum, you should avoid sharing any session cookie or identifier with the API key lookup path. Instead, authenticate via the key, then establish a fresh session or issue a short-lived token that is unrelated to the pre-auth session ID.
Below is a syntactically correct example using axum-sessions with API key validation. The key is validated, and upon success, the session is regenerated:
use axum::{routing::get, Router};
use axum_sessions::{SessionLayer, SessionStore};
use std::net::SocketAddr;
async fn validate_api_key(key: &str) -> bool {
// Compare against a secure store; this is simplified
key == "valid_key_123"
}
async fn handler(session: axum_sessions::Session) -> String {
if let Some(user) = session.get::("user") {
format!("Authenticated as {}", user)
} else {
"Unauthorized".to_string()
}
}
#[tokio::main]
async fn main() {
let store = SessionStore::default();
let layer = SessionLayer::new(store, "session_key".into_bytes().into());
let app = Router::new()
.route("/protected", get(handler))
.layer(layer)
.route("/login", get(login_handler));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
axum::Server::bind(&addr).serve(app.into_make_service()).await.unwrap();
}
async fn login_handler(
axum_sessions::Session(session): axum_sessions::Session,
headers: axum::http::HeaderMap,
) -> String {
let api_key = headers.get("Authorization")
.and_then(|v| v.to_str().ok())
.filter(|s| s.starts_with("ApiKey "))
.map(|s| s.trim_start_matches("ApiKey "));
if let Some(key) = api_key {
if validate_api_key(key).await {
// Regenerate session to prevent fixation
session.rotate();
session.insert("user", "alice").unwrap();
return "Logged in".to_string();
}
}
"Invalid key".to_string()
}
In this pattern, session.rotate() ensures a new session ID is issued after authentication, breaking any fixation chain. The API key is used only for authentication, not for session lookup. For stateless designs, replace sessions with a short-lived JWT issued after key validation, ensuring the JWT subject does not derive from any pre-auth identifier. middleBrick’s CLI can be used to verify that endpoints do not return the same session or token when the same API key is presented before and after login.
Additionally, avoid logging or caching API keys alongside session identifiers, and ensure that the key validation logic does not accidentally reuse the same cryptographic nonce or identifier. The Pro plan’s continuous monitoring can alert you if scan results show Authentication or BOLA/IDOR findings after changes to your Axum routes.