Jwt Misconfiguration in Actix with Jwt Tokens
Jwt Misconfiguration in Actix with Jwt Tokens — how this specific combination creates or exposes the vulnerability
JWT misconfiguration in Actix applications often arises when tokens are issued or validated without enforcing strict algorithms, expiration checks, or proper key management. Actix-web is a popular Rust framework for building HTTP services, and it is commonly used with JWT libraries such as jsonwebtoken to handle authorization. When JWT tokens are accepted without validating the algorithm (e.g., accepting none or HS256 when RS256 is expected), or when public keys are not properly pinned, attackers can forge tokens or escalate privileges.
One concrete scenario involves an Actix endpoint that relies on bearer JWT tokens but does not enforce token binding or audience validation. If the middleware decodes tokens without verifying the issuer (iss) or the intended audience (aud), a token issued for one service may be accepted by another service within the same ecosystem. This can lead to horizontal privilege escalation, where one user gains access to another user’s resources. Additionally, if the secret or private key is weak, or if the key is exposed in client-side code, attackers can sign their own tokens and bypass authentication.
Insecure default configurations compound the risk. For example, some Actix integrations may skip revocation checks or fail to validate the nbf (not before) claim, allowing replay attacks. Because JWTs are often stored in cookies or local storage, missing Secure and HttpOnly flags in conjunction with weak token validation can enable cross-site scripting (XSS) driven token theft. The combination of permissive parsing, missing signature verification, and missing contextual checks (such as IP or device binding) means that a compromised token can be used across the API surface until expiration.
middleBrick detects these patterns by correlating OpenAPI/Swagger specifications with runtime behavior. For instance, if the spec declares a security scheme requiring JWT with RS256, but runtime probes show the endpoint also accepts unsigned tokens or HS256, this inconsistency is flagged as a high-severity finding. The scanner checks for missing mandatory claims, weak signing configurations, and missing HTTPS enforcement in authorization headers, highlighting how misconfigured JWT handling can be leveraged in chained attacks such as IDOR or privilege escalation.
Jwt Tokens-Specific Remediation in Actix — concrete code fixes
To remediate JWT misconfiguration in Actix, enforce strict algorithm validation, verify all standard claims, and bind tokens to their intended context. Use the jsonwebtoken crate with explicit key material and avoid default or permissive settings. Below are concrete, secure code examples for Actix middleware and handler implementations.
Secure JWT validation middleware in Actix
Define a middleware or extractor that decodes and validates tokens with algorithm and claim checks:
use actix_web::{dev::ServiceRequest, Error, FromRequest, HttpMessage};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation, Header};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
iss: String,
aud: String,
exp: usize,
nbf: usize,
}
struct AuthenticatedUser {
claims: Claims,
user_id: String,
}
impl FromRequest for AuthenticatedUser {
type Error = Error;
type Future = std::future::Ready>;
type Config = ();
fn from_request(req: &actix_web::HttpRequest, _: &mut actix_web::dev::Payload) -> Self::Future {
let auth = BearerAuth::from_request(req, _).map_err(|_| actix_web::error::ErrorUnauthorized("Invalid auth"))?;
let token = auth.token();
// Enforce expected algorithm and required claims
let mut validation = Validation::new(Algorithm::RS256);
validation.set_audience(&["my-api.example.com"]);
validation.set_issuer(&["auth.example.com"]);
validation.required_spec_claims.insert("exp");
validation.required_spec_claims.insert("nbf");
validation.required_spec_claims.insert("iss");
validation.required_spec_claims.insert("aud");
let key = DecodingKey::from_rsa_pem(include_bytes!("/path/to/public_key.pem")).expect("valid key");
match decode::(token, &key, &validation) {
Ok(token_data) => {
let user = AuthenticatedUser {
claims: token_data.claims,
user_id: token_data.claims.sub,
};
std::future::ready(Ok(user))
}
Err(_) => std::future::ready(Err(actix_web::error::ErrorUnauthorized("Invalid token"))),
}
}
}
async fn protected_route(user: AuthenticatedUser) -> String {
format!("Hello user: {}", user.user_id)
}
Ensure that the public key is loaded from a trusted source and that key rotation is supported via JWKS with strict pinning. Avoid using Algorithm::HS256 with shared secrets in distributed systems; prefer RS256 with asymmetric keys.
Token issuance with strict settings
When issuing tokens in an Actix handler, explicitly set algorithm, audience, issuer, and short expiration:
use jsonwebtoken::{encode, Header, EncodingKey};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
iss: String,
aud: String,
exp: usize,
nbf: usize,
}
fn issue_token(user_id: &str) -> String {
let claims = Claims {
sub: user_id.to_string(),
iss: "auth.example.com".to_string(),
aud: "my-api.example.com".to_string(),
exp: (chrono::Utc::now() + chrono::Duration::minutes(15)).timestamp() as usize,
nbf: chrono::Utc::now().timestamp() as usize,
};
encode(
&Header::new(Algorithm::RS256),
&claims,
&EncodingKey::from_rsa_pem(include_bytes!("/path/to/private_key.pem")).expect("valid key"),
).expect("valid encoding")
}
Always transmit JWTs over HTTPS, set short expirations, and store tokens in HttpOnly, Secure cookies when used in browsers. Validate tokens on every protected route and reject tokens with missing or mismatched claims.
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 |