Auth Bypass in Actix with Saml
Auth Bypass in Actix with Saml — how this specific combination creates or exposes the vulnerability
In Actix-based applications that rely on SAML for authentication, an Auth Bypass can occur when the application processes SAML responses without rigorously validating the issuer, audience, or session state. SAML relies on trust between the Identity Provider (IdP) and the Service Provider (SP). If the SP implementation does not enforce strict signature verification and binding of the SAML response to the intended recipient, an attacker may be able to inject a crafted response or reuse a valid assertion across different service contexts.
For example, an application might accept a SAML response that was intended for another service or fail to validate the AudienceRestriction condition. This can allow an authenticated session from one tenant or service to be accepted as valid for another, effectively bypassing expected access controls. In Actix, if the route guards or middleware that enforce authorization are applied inconsistently—such as allowing unauthenticated access to certain endpoints while still accepting a SAML-authenticated session—an authenticated but unauthorized user can reach protected resources.
The risk is compounded when the application mixes authentication mechanisms or falls back to unauthenticated routes in error paths. An attacker could leverage an unauthenticated endpoint to probe for misconfigured route guards and then use a valid SAML assertion to escalate privileges across scopes or services. This pattern is commonly flagged in middleBrick scans under Authentication and BOLA/IDOR checks, especially when the scan detects inconsistent enforcement of identity context across handlers.
middleBrick’s LLM/AI Security checks are not relevant to this vector, but its Authentication and BOLA/IDOR checks can surface these gaps by correlating route-level access rules with SAML response validation results. The scan also cross-references the OpenAPI spec’s security schemes with runtime behavior, highlighting where SAML-based authentication is declared but not consistently enforced.
Saml-Specific Remediation in Actix — concrete code fixes
Remediation focuses on strict validation of SAML responses, audience and issuer checks, and consistent authorization enforcement across all Actix routes.
- Validate the SAML response signature and enforce audience and issuer constraints. Use a trusted SAML library and ensure certificate pinning.
- Bind the SAML session to the intended recipient URL and enforce
AudienceRestrictionon every assertion. - Apply authorization middleware uniformly and avoid unauthenticated fallbacks for sensitive routes.
Example SAML configuration and validation in Actix using the actix-identity and a SAML library (illustrative; adapt to your SAML provider):
use actix_web::{web, App, HttpServer, HttpResponse, middleware::Logger};
use actix_identity::{Identity, CookieIdentityPolicy, IdentityService};
use saml_agent::SamlResponse; // illustrative library
async fn saml_login_callback(identity: Identity, payload: web::Form>) -> HttpResponse {
let saml_response = payload.get("SAMLResponse").and_then(|v| base64::decode(v).ok());
let saml_response = match saml_response {
Some(raw) => String::from_utf8_lossy(&raw).to_string(),
None => return HttpResponse::BadRequest().body("Missing SAMLResponse"),
};
// Validate signature, audience, issuer, and not-before/not-on-or-after
let validated = SamlResponse::validate(
&saml_response,
"https://sp.example.com/acs",
"https://idp.example.com",
&saml_agent::CertificatePinner::from_pem(include_bytes!("idp_cert.pem")),
);
match validated {
Ok(claims) => {
identity.remember(format!("{}|{}", claims.name_id, claims.session_index));
HttpResponse::SeeOther()
.insert_header((actix_web::http::header::LOCATION, "/app/dashboard"))
.finish()
}
Err(e) => {
// Do not fall back to unauthenticated access
HttpResponse::Unauthorized().body(format!("Invalid SAML: {}", e))
}
}
}
// Enforce authenticated access on protected routes
async fn protected_route(identity: Identity) -> HttpResponse {
if let Some(_user) = identity.identity() {
HttpResponse::Ok().body("Access granted")
} else {
HttpResponse::Unauthorized().body("Authentication required")
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "actix_web=info");
env_logger::init();
HttpServer::new(|| {
App::new()
.wrap(Logger::default())
.wrap(
IdentityService::new(
CookieIdentityPolicy::new(&[0; 32])
.name("auth-cookie")
.secure(false), // set true in production with HTTPS
)
.into(),
)
.route("/login/saml", web::post().to(saml_login_callback))
.route("/app/secure", web::get().to(protected_route))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Key points in the example:
- SAML response is decoded and validated with explicit audience (
https://sp.example.com/acs) and issuer (https://idp.example.com) checks. - Identity is stored only after successful validation; no fallback to unauthenticated state.
- Protected routes consistently check
identity.identity()to ensure every handler enforces authentication.
Additionally, review your OpenAPI spec to confirm that SAML-based security schemes are declared and that path-level security requirements align with the identity provider’s scopes and roles. middleBrick’s Pro plan continuous monitoring can help detect regressions in route-level enforcement over time.
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 |