Api Key Exposure in Aspnet with Saml
Api Key Exposure in Aspnet with Saml — how this specific combination creates or exposes the vulnerability
When an ASP.NET application embeds API keys within SAML artifacts or relies on SAML attributes to convey secrets, the security boundary between identity and access management can break down. SAML assertions are typically signed and optionally encrypted, but developers sometimes place non-identity data such as API keys inside NameID, Role, or custom AttributeStatement fields. If the relying party trusts the SAML assertion without additional validation, these embedded keys can be elevated to application-level credentials, effectively turning an identity token into a bearer token.
ASP.NET SAML stacks often use WIF or third-party libraries such as Kentor.AuthServices. Misconfiguration is common when developers map SAML claims directly to application roles or API key variables without verifying audience, issuer, or intended purpose. For example, an assertion containing an attribute named api_key may be deserialized and assigned to Thread.CurrentPrincipal claims, and later used to authorize outbound service calls. Because SAML messages can be captured in transit if HTTPS is not enforced end-to-end, or if metadata endpoints are exposed, an attacker with network access or a compromised identity provider may extract the embedded key.
Another vector arises from artifact resolution flows. SAML artifacts are references that trigger backend resolution via the SAML protocol binding. If the artifact resolution endpoint in ASP.NET does not validate the source IP or requires weak authentication, an attacker can intercept or forge artifact responses and inject a crafted assertion containing a valid-looking API key. The application, trusting the artifact binding as an authenticated context, may instantiate service clients using the attacker-supplied key, leading to unauthorized access to third-party services.
Additionally, replay and assertion freshness issues can amplify exposure. SAML assertions carry NotBefore and NotOnOrAfter timestamps, but ASP.NET applications may skip strict validation, accepting stale assertions that contain outdated API keys. If the relying party caches keys extracted from assertions, rotation on the identity provider side may not be reflected, leaving the application with a stale credential. Logging practices can compound the risk: if SAML responses or debug traces inadvertently write API keys to logs or telemetry, those keys can be exfiltrated through log access or error reporting channels.
These risks align with the broader OWASP API Top 10, particularly Broken Object Level Authorization (BOLA) and Security Misconfiguration, because the boundary between identity and access control is blurred. Unlike OAuth tokens, SAML was not originally designed for machine-to-machine delegation; repurposing it to carry API keys increases the attack surface. Regular scans using tools like middleBrick can surface these issues by detecting unauthenticated endpoints, insecure metadata handling, and anomalous attribute mappings, providing prioritized findings and remediation guidance before production exposure.
Saml-Specific Remediation in Aspnet — concrete code fixes
Remediation focuses on strict validation, separation of concerns, and avoiding the use of SAML assertions as bearer credentials. First, enforce HTTPS for all SAML endpoints, including SingleLogoutService and ArtifactResolutionService, and validate issuer and audience constraints in the Saml2SecurityTokenHandler. Do not map SAML attributes that convey secrets directly to application-level API keys; instead, use claims for identity and retrieve keys from a secure vault at runtime.
In ASP.NET, configure the Saml2Configuration with tightened token validation. The following C# example shows how to set up a SAML 2.0 relying party with strict audience and issuer checks, and how to avoid storing API keys in claims:
// Example using Kentor.AuthServices with strict validation
var options = new Saml2Configuration {
Issuer = "https://app.example.com/saml",
SigningKeys = new X509Certificate2Collection(
new X509Certificate2("path/to/app.crt")),
AllowedAudienceUris = new[] { new Uri("https://app.example.com/") },
IdentityProviders = {
new IdentityProvider(
new EntityId("https://idp.example.com/metadata"),
options.SigningKeys) {
LoadMetadata = true,
WantAssertionsSigned = true,
AllowUnsolicitedAuthnResponse = false,
Binding = Saml2BindingType.HttpRedirect
}
},
CertificateValidationMode = X509CertificateValidationMode.ChainTrust,
RevocationMode = X509RevocationMode.Online
};
app.UseKentorAuthServicesAuthentication(options);
When consuming SAML from an identity provider, map only identity claims (NameID, Email, Role) and explicitly reject any attribute named api_key or similar. Use the following handler to filter sensitive attributes before they enter the claims pipeline:
app.Use(async (context, next) => {
var samlHandler = context.RequestServices.GetRequiredService<Saml2SecurityTokenHandler>();
context.Authentication.SignInAsync(...);
// Inspect incoming assertions and drop sensitive attributes
var principal = samlHandler.ReadToken(token) as ClaimsPrincipal;
var filteredIdentities = principal.Identities.Select(id => {
var filtered = new ClaimsIdentity(id);
foreach (var claim in id.Claims) {
if (claim.Type != "api_key") {
filtered.AddClaim(claim);
}
}
return filtered;
});
context.User = new ClaimsPrincipal(filteredIdentities);
await next();
});
For artifact resolution, ensure that the endpoint validates the source of the artifact and ties resolution to the authenticated session. Do not allow artifacts to be resolved with elevated trust unless the message is re-validated against the original issuer metadata. The following snippet demonstrates binding validation and avoiding key propagation:
// Validate artifact resolution in an ASP.NET endpoint
[HttpPost("Saml/Artifact")]
public IActionResult Artifact([FromBody] ArtifactResolveRequest request) {
if (!ModelState.IsValid) return BadRequest();
// Verify the artifact origin matches the IdentityProvider binding
if (!samlArtifactValidator.IsValid(request.Artifact, User.Identity as ClaimsIdentity)) {
return Unauthorized();
}
// Resolve assertion without extracting API keys into claims
var saml2Assertion = samlArtifactResolver.Resolve(request.Artifact);
// Use identity claims only; fetch API key securely at call time
var apiKey = secureVault.GetKeyForService(saml2Assertion.Issuer);
// Proceed with service client using runtime-retrieved key
return Ok();
}
Finally, rotate keys independently of SAML identity lifetimes and avoid logging assertion contents. Configure your ASP.NET application to reject unsigned or improperly encrypted assertions, and regularly inspect metadata for endpoint changes. middleBrick can complement these efforts by scanning your unauthenticated attack surface and highlighting misconfigured SAML endpoints or overly permissive attribute mappings, delivering prioritized findings and remediation guidance within 5–15 seconds.