HIGH api key exposureaxumsaml

Api Key Exposure in Axum with Saml

Api Key Exposure in Axum with Saml — how this specific combination creates or exposes the vulnerability

When an Axum service uses SAML for identity federation, developers sometimes pass long-lived API keys or shared secrets as URL query parameters or custom HTTP headers to downstream services. If the SAML flow does not enforce strict redirect validation, an attacker can craft a malicious SAML response or relay state that causes the application to include these keys in outbound requests to attacker-controlled endpoints. Because Axum handlers typically reuse HTTP clients across requests, a single compromised key can expose multiple integrations.

During a black-box scan, middleBrick tests unauthenticated endpoints that accept SAML assertions or SAML metadata. It checks whether API keys appear in URLs, request headers, or logs that may be influenced by SAML attributes. For example, if a handler extracts a RelayState parameter and uses it to build a request with an API key in the query string, middleBrick can detect exposed keys by inspecting outbound HTTP calls made during the scan. The scanner also looks for missing binding between SAML subject confirmation and the application’s authorization logic, which can allow a malicious identity provider to submit assertions that lead to unintended key usage.

Common real-world patterns that lead to exposure include:

  • Using SAML attributes to dynamically construct service account keys without additional verification.
  • Embedding API keys in redirect URLs that are not validated against a strict allow-list.
  • Logging SAML responses or headers that inadvertently include keys or secrets.

Because Axum applications often integrate with cloud services via HTTP clients, any key that reaches an untrusted network path can be intercepted. middleBrick flags these findings with severity and remediation guidance, noting that the scanner detects issues but does not apply fixes.

Saml-Specific Remediation in Axum — concrete code fixes

Remediation focuses on preventing API keys from being influenced by SAML data and ensuring strict validation of SAML responses. Do not derive secrets from SAML attributes, and avoid including keys in URLs. Use environment variables or secure vaults for keys, and bind them to the application’s own authorization checks rather than to SAML assertions.

Below are concrete Axum examples that demonstrate secure handling when SAML is used for identity.

1. SAML metadata and endpoint parsing (no keys in URLs)

Parse SAML metadata from a static file and configure endpoints without dynamic key injection.

use saml2::{Config, MetadataUrl};
use axum::routing::get;
use axum::Router;

#[tokio::main]
async fn main() {
    // Load SAML configuration from a file, not from user input
    let config = Config::from_metadata_url(MetadataUrl::new("file:///etc/saml/metadata.xml").unwrap())
        .expect("valid metadata");

    let app = Router::new()
        .route("/saml/acs", get(move |_| async { "ACS endpoint configured securely" }))
        .with_config(config);

    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

2. RelayState validation to prevent open redirects and key leakage

Validate RelayState strictly and do not use it to construct request URLs that include API keys.

use axum::extract::Query;
use serde::Deserialize;

#[derive(Deserialize)]
struct SamlQuery {
    relay_state: Option,
}

async fn acs_handler(
    Query(params): Query,
) -> Result {
    let allowed_hosts = ["app.example.com"];
    let relay = params.relay_state.unwrap_or_default();

    // Reject relay states that do not match allowed hosts
    if !allowed_hosts.iter().any(|h| relay.starts_with(&format!("https://{}", h))) {
        return Err((http::StatusCode::BAD_REQUEST, "invalid relay state".into()));
    }

    // Do NOT append API keys to the relay URL
    Ok(format!("Relay accepted: {}", relay))
}

3. Using environment-bound keys instead of SAML-derived secrets

Load service keys from environment variables and keep them independent from SAML attributes.

use axum::extract::State;
use std::sync::Arc;

struct ApiKeyState {
    key: String,
}

async fn call_downstream(State(state): State>) -> String {
    // Key comes from secure configuration, not from SAML
    reqwest::Client::new()
        .get("https://api.example.com/v1/data")
        .bearer_auth(&state.key)
        .send()
        .await
        .map(|r| r.text().unwrap_or_default())
        .unwrap_or_default()
}

These patterns ensure that SAML is used strictly for identity and that API keys remain outside the SAML flow. middleBrick can verify that no exposed keys are influenced by SAML parameters during a scan.

Frequently Asked Questions

Can middleBrick detect exposed API keys in SAML-based Axum applications?
Yes. middleBrick scans unauthenticated endpoints and checks whether API keys appear in URLs, headers, or logs that may be influenced by SAML attributes. It reports exposure findings with severity and remediation guidance, but it does not fix or block the exposure.
Does using SAML metadata eliminate the need for secure key storage in Axum?
No. SAML metadata helps configure identity flows, but long-lived API keys must still be stored securely (for example in environment variables or a vault) and managed independently from SAML attributes. middleBrick checks for insecure key handling but does not manage keys.