Api Key Exposure in Spring Boot with Saml
Api Key Exposure in Spring Boot with Saml — how this specific combination creates or exposes the vulnerability
When a Spring Boot application uses SAML for authentication, developers often focus on the protocol flow—assertion validation, Single Logout, and user role mapping—while overlooking how API keys are handled in the same runtime context. If an API key is stored as a plain string in application properties, passed through HTTP headers without encryption, or logged inadvertently, the combination of SAML’s session management and key usage can expose that key to unintended parties.
Spring Boot applications frequently consume external services using API keys, and these keys can appear in several risky places when SAML is in play. For example, a service client may be configured with a key read from application.yml and then used to call a third‑party API from a controller or a service invoked after SAML authentication. If the endpoint is not properly protected by transport security or if the application accidentally exposes debug information, the key may be reflected in responses, error messages, or logs. Because SAML assertions carry user identity and sometimes group memberships, an attacker who can influence authorization logic or session handling may leverage that context to trigger API calls that leak the key in logs or error responses.
Misconfigured SAML metadata or relying party registration can also contribute to exposure. If the Spring Security SAML extension (or a custom integration) does not strictly validate endpoints and bindings, an attacker might manipulate authentication flows to cause the application to use incorrect or overly permissive configurations. This can lead to scenarios where API keys are included in URLs as query parameters—visible in browser history, server logs, and proxy logs—rather than being passed in headers or using more secure mechanisms. Insecure deserialization of SAML responses, if the application processes raw assertions in a permissive way, can also open paths for injection or session fixation that indirectly facilitate access to key-bearing requests.
Consider a concrete pattern: a controller method that calls a payment provider using a static API key stored in a bean. If SAML authentication establishes the current user but the service method does not enforce additional authorization checks, an attacker who compromises or elevates privileges might invoke the method in a way that causes the key to be printed during troubleshooting or emitted in verbose logging. Even if the key itself is not returned to the client, exposure in logs or through introspection endpoints can lead to credential leakage. The risk is compounded when the application uses reflection or dynamic client builders that obscure which keys are in play, making it harder to track where in the call chain a given key is used.
To detect such issues, scanning tools look for patterns like hard‑coded keys in configuration snippets, missing HTTPS enforcement on external calls, and overly verbose logging that includes sensitive headers. They also examine SAML configuration for weak certificate validation or missing endpoint constraints that could allow an attacker to steer authentication state toward paths where keys are used. Because the risk emerges from the interaction between identity management and key usage—not from a single flaw alone—the findings often highlight multiple weak points that, when chained, increase the likelihood of exposure.
Saml-Specific Remediation in Spring Boot — concrete code fixes
Remediation centers on isolating API keys from authentication state, enforcing strict transport and storage rules, and ensuring SAML configuration follows security best practices. Avoid storing keys in properties that might be inadvertently logged or exposed via debug endpoints; instead, use environment variables or a secrets provider and reference them with placeholders. Ensure all external API calls use HTTPS and that keys are transmitted only in secure headers, never in URLs.
Below are concrete configuration and code examples for a Spring Boot application using SAML.
Secure SAML Configuration with Key Isolation
Define your API key as an environment variable and reference it in your configuration. Keep SAML settings strict and avoid permissive metadata imports.
api-key=${EXTERNAL_API_KEY}
In application.yml:
saml:
key-store:
location: classpath:keystore.jks
password: ${KEYSTORE_PASSWORD}
alias: saml
relying-party:
registration:
my-idp:
signing-credentials:
- certificate-location: classpath:saml-certificate.pem
private-key-location: classpath:saml-private.key
metadata:
location: classpath:metadata/idp-metadata.xml
assertion-consumer-service-url: https://app.example.com/saml/sso
single-logout-service-url: https://app.example.com/saml/slo
force-authn: true
want-authn-requests-signed: true
require-signed-assertions: true
entity-id: https://app.example.com/saml/metadata
include-name-id: true
name-id-format: urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
extended-metadata:
idp-entity-name: <idp-entity-id>
signing-algorithm: SHA256withRSA
encryption-algorithm: RSA-OAEP
metadata-include-extensions: false
This configuration ensures that signing and encryption use strong algorithms, assertions are validated, and external metadata is not loaded from untrusted locations.
Safe API Key Usage in a Service Client
Create a service that reads the key from the environment and uses it in headers over HTTPS. Do not log the key or include it in error messages.
@Service
public class ExternalApiService {
private final String apiKey;
private final RestTemplate restTemplate;
public ExternalApiService(
@Value("${api-key}") String apiKey,
RestTemplateBuilder restTemplateBuilder) {
this.apiKey = apiKey;
this.restTemplate = restTemplateBuilder.build();
}
public String callExternal(String resource) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + apiKey);
headers.set("Accept", "application/json");
HttpEntity<String> request = new HttpEntity<>(headers);
return restTemplate.exchange(
"https://api.example.com/" + resource,
HttpMethod.GET,
request,
String.class)
.getBody();
}
}
This approach avoids exposing the key in logs and ensures it is only used in secure outbound calls. If you need to integrate with SAML context (e.g., to scope calls per user), pass the user identity separately and do not embed the key in the assertion or session attributes.
Logging and Error Handling Safeguards
Configure logging to redact sensitive headers and avoid dumping request or response bodies that might contain key references. In a Spring Boot application, you can customize CommonsRequestLoggingFilter or use a servlet filter to scrub headers.
@Component
public class SensitiveHeaderFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
HttpServletRequest wrapped = new HttpServletRequestWrapper(request) {
@Override
public String getHeader(String name) {
if ("Authorization".equalsIgnoreCase(name)) {
return "[redacted]";
}
return super.getHeader(name);
}
};
filterChain.doFilter(wrapped, response);
}
}
Additionally, ensure that SAML processing does not inadvertently echo user-provided input into logs or error pages. Validate and sanitize any data extracted from SAML assertions before using it in diagnostics.