Cross Site Request Forgery in Actix with Bearer Tokens
Cross Site Request Forgery in Actix with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Cross Site Request Forgery (CSRF) in Actix with Bearer Tokens arises when authenticated state relies solely on a bearer token (e.g., an access token in an Authorization header) without additional anti‑CSRF protections. Bearer tokens are typically stored in browser-accessible locations such as localStorage or sessionStorage, or inadvertently leaked via browser history or referrer headers. Because these tokens are automatically included by browsers in cross-origin requests when attacker-controlled pages construct requests (e.g., via fetch or XMLHttpRequest), an attacker can trick a logged‑in user into issuing state‑changing HTTP requests to your Actix API endpoints.
In a typical Actix web service, authentication may be implemented by extracting a Bearer token from the Authorization header, validating it, and deriving an identity for the request. If the endpoint performs sensitive operations—such as changing email, updating payment information, or modifying permissions—and does not verify the request origin or require a same-site cookie or a custom header, the request will succeed when initiated by an attacker’s page. This is because the browser attaches the bearer token automatically, making the API believe the request is legitimate. For example, an attacker’s page can include an image tag or a form submission that targets your Actix endpoint, leveraging the user’s existing token without their knowledge. The absence of a SameSite attribute on cookies (if used in tandem), plus the token’s presence in JavaScript-accessible storage, increases the risk surface. Even if your API does not set cookies, token leakage through browser features or misconfigured CORS can allow a malicious site to craft authenticated requests on behalf of the victim.
An Actix API that validates Bearer tokens but lacks CSRF mitigations is vulnerable when the token is exposed to a browser context. Consider a scenario where the token is stored in localStorage and retrieved in JavaScript for Authorization headers. Any script injected via XSS can read the token and forge requests, but even without XSS, a crafted cross‑origin request can exploit the browser’s automatic inclusion of credentials in the Authorization header under certain conditions. The CSRF chain is completed when the request changes application state, and the API processes it based solely on the bearer token without origin checks, custom headers, or synchronizer tokens.
Real‑world attack patterns often involve a combination of CSRF and token handling weaknesses, such as missing SameSite attributes or overly permissive CORS. For instance, an attacker may host a malicious form on another domain that submits a PATCH request to https://api.example.com/users/me/email with a new email. If the user’s browser holds a valid Bearer token and the Actix endpoint relies only on that token for authentication, the request will be processed successfully by middleBrick scans for sensitive endpoints, highlighting the need for layered defenses. Reference to frameworks such as OAuth 2.0 access tokens and common misconfigurations underscores the importance of treating bearer credentials as you would session cookies—protecting them against cross‑origin use.
To understand the exposure, it is helpful to align CSRF considerations with the OWASP API Top 10 and related standards. When an Actix service processes bearer tokens without additional origin verification, it mirrors risks found in traditional session‑based CSRF but with token‑centric nuances. This is why scanning tools like middleBrick include CSRF checks within their authentication and property authorization tests, ensuring that endpoints expecting bearer tokens also enforce anti‑CSRF controls such as custom headers or SameSite cookies where applicable.
Bearer Tokens-Specific Remediation in Actix — concrete code fixes
Remediation for CSRF when using Bearer Tokens in Actix focuses on preventing unauthorized cross‑origin requests while preserving legitimate API usage. Because bearer tokens are often managed outside cookies, the primary defenses are requiring custom headers, enforcing strict CORS, and avoiding reliance on tokens that can be automatically sent by browsers. Below are concrete, realistic code examples for an Actix web application.
1. Require a custom header for state‑changing requests. Browsers do not automatically add custom headers like X-Requested-With or X-CSRF-Token in cross‑origin requests, making this an effective mitigation. Combine this with CORS that does not expose credentials to untrusted origins.
use actix_web::{web, App, HttpResponse, HttpServer, Responder, HttpRequest};
use actix_cors::Cors;
async fn change_email(req: HttpRequest, web::Json(payload): web::Json<serde_json::Value>) -> impl Responder {
// Require a custom header to prove the request is same-origin
if req.headers().get("X-CSRF-Token").is_none() {
return HttpResponse::Forbidden().body("Missing CSRF token header");
}
// Validate the token matches the session or origin expectation
// ... your business logic
HttpResponse::Ok().body("Email updated")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let cors = Cors::default()
.allowed_origin("https://your-trusted-frontend.com")
.allowed_methods(vec!["GET", "POST"])
.allowed_headers(vec!["Authorization", "Content-Type", "X-CSRF-Token"])
.max_age(3600)
.supports_credentials();
HttpServer::new(move || {
App::new()
.wrap(cors)
.route("/users/me/email", web::post().to(change_email))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
2. If you must use cookies for bearer storage (e.g., for compatibility), set the SameSite attribute to Strict or Lax and avoid HttpOnly only if necessary for your client-side logic. This prevents the browser from sending the cookie on cross‑site requests. For APIs that rely on Authorization headers, ensure cookies are not used for bearer storage unless necessary.
// Example of setting a SameSite cookie alongside bearer usage for non‑API flows
use actix_web::cookie::{Cookie, SameSite};
use actix_web::HttpResponse;
fn set_secure_cookie() -> HttpResponse {
let mut cookie = Cookie::build("session_token", "value")
.same_site(SameSite::Strict)
.secure(true)
.http_only(true)
.finish();
HttpResponse::Ok()
.cookie(cookie)
.body("Authenticated")
}
3. Validate the Origin header for requests where the bearer token is presented in headers. This is not sufficient alone due to header spoofing risks in non‑browser contexts, but it adds a layer for browser‑initiated requests.
async fn validate_origin(req: &HttpRequest) -> bool {
if let Some(origin) = req.headers().get("Origin") {
if let Ok(origin_str) = origin.to_str() {
return origin_str == "https://your-trusted-frontend.com";
}
}
false
}
4. Use the middleBrick CLI to verify that your endpoints enforce these controls. Run middlebrick scan <url> to identify missing CSRF mitigations and review the findings in the dashboard or via JSON output. The scanner will highlight endpoints that accept bearer tokens without required headers or restrictive CORS, enabling you to tighten your configuration.
These examples demonstrate practical steps to reduce CSRF risk when Bearer Tokens are in use. Always combine header checks, strict CORS, and regular scans to maintain a robust security posture.