HIGH api key exposureaspnetopenid connect

Api Key Exposure in Aspnet with Openid Connect

Api Key Exposure in Aspnet with Openid Connect — how this specific combination creates or exposes the vulnerability

In ASP.NET applications that use OpenID Connect (OIDC) for authentication, API key exposure often occurs when developers inadvertently embed or log sensitive credentials used to back the OIDC client. OIDC itself is a protocol built on OAuth 2.0 and does not prescribe a specific mechanism for API keys; however, applications often require a client secret or a machine-to-machine API key to communicate with the identity provider’s token endpoint or to call downstream protected APIs. When these keys are stored in configuration files, source code, or logs, they become exposure risks that can be discovered by black-box scans.

ASP.NET Core’s OIDC middleware (e.g., AddOpenIdConnect) typically requires a ClientId and, in many deployments, a ClientSecret. If the ClientSecret is hardcoded or stored in plaintext in appsettings.json without protection, and if the application also exposes an endpoint that returns configuration or debug information, a scanner can detect the leakage through unauthenticated endpoints or error messages. For example, an endpoint that echoes configuration for diagnostic purposes might return the ClientSecret in responses, which middleBrick’s unauthenticated checks can identify as exposed data. Additionally, if the application uses API keys to authorize calls to external services and those keys are passed in request headers that are logged or reflected in responses, the combination of OIDC-based identity flows and key-based authorization can amplify the blast radius: an exposed API key may allow access to privileged resources, and if combined with a leaked OIDC client secret, an attacker can forge tokens or impersonate the application.

During a scan, middleBrick’s checks for Data Exposure and Authentication interact with the OIDC flow by probing unauthenticated surfaces to see whether tokens, keys, or configuration details are returned. For instance, the scanner might send requests to token introspection or userinfo endpoints with or without partial credentials to see if responses include sensitive metadata. If the application includes an inventory of integrated services (e.g., downstream APIs identified in the OIDC scopes), the scanner’s Inventory Management and Unsafe Consumption checks can map which keys are referenced and whether they are transmitted insecurely. This is particularly relevant when OIDC is used not only for user authentication but also to obtain access tokens for calling other APIs; if those downstream APIs require an API key and the key is embedded in client-side code or transmitted over insecure channels, the scanner’s Data Exposure and Encryption checks will flag it. The interplay between OIDC flows and key-based authorization means that a single misconfiguration—such as logging tokens with keys or failing to restrict key usage to server-side components—can expose multiple sensitive artifacts in a single scan cycle.

To illustrate, consider an ASP.NET Core app that uses AddOpenIdConnect and also calls a third-party service protected by an API key. A realistic but minimal server-side controller might look like this, where the key is read from configuration and used in outbound requests:

using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using System.Net.Http;
using System.Threading.Tasks;

[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    private readonly IConfiguration _config;
    private readonly IHttpClientFactory _clientFactory;

    public OrdersController(IConfiguration config, IHttpClientFactory clientFactory)
    {
        _config = config;
        _clientFactory = clientFactory;
    }

    [HttpGet("details")]
    public async Task<IActionResult> GetDetails()
    {
        var apiKey = _config["ExternalService:ApiKey"];
        if (string.IsNullOrEmpty(apiKey))
        {
            return StatusCode(500, "Missing API key");
        }

        var client = _clientFactory.CreateClient();
        client.DefaultRequestHeaders.Add("X-API-Key", apiKey);
        var response = await client.GetAsync("https://external.example.com/orders");
        var content = await response.Content.ReadAsStringAsync();
        return Ok(content);
    }
}

If ExternalService:ApiKey is stored in plaintext in appsettings.json and the application does not restrict access to the configuration endpoint, a middleBrick scan can detect the exposure through configuration introspection or log leakage. Moreover, if the OIDC client secret is also stored in the same configuration file, the scan’s Authentication and Data Exposure checks can correlate findings to indicate a high-risk combination where both identity and authorization keys are exposed.

Risk prioritization in such scenarios considers the severity of key exposure alongside the OIDC context: an exposed API key that allows direct access to external services is high severity, while a leaked OIDC client secret enabling token forgery is critical. The scanner’s findings will map these to OWASP API Top 10 (e.g., A07:2021 Identification and Authentication Failures) and compliance frameworks like PCI-DSS and SOC2, highlighting that improper secret management in OIDC-integrated applications can lead to unauthorized access and data exfiltration.

Openid Connect-Specific Remediation in Aspnet — concrete code fixes

Remediation focuses on secure handling of secrets used by OpenID Connect and on ensuring API keys are never exposed to clients or logs. In ASP.NET Core, store sensitive values like ClientSecret and external API keys using secure configuration providers and environment variables, and avoid reflecting them in responses or logs. Use the Data Protection API for additional protection in non-Kubernetes environments, and ensure that configuration endpoints are not exposed publicly.

For OIDC client secrets, prefer environment variables or Azure Key Vault/equivalent, and reference them via configuration without hardcoding. Here is a secure configuration and code pattern for an ASP.NET Core app using AddOpenIdConnect, where secrets are injected at runtime:

// Program.cs
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "OpenIdConnect";
})
.AddCookie("Cookies")
.AddOpenIdConnect("OpenIdConnect", options =>
{
    options.Authority = builder.Configuration["OpenIdConnect:Authority"];
    options.ClientId = builder.Configuration["OpenIdConnect:ClientId"];
    options.ClientSecret = builder.Configuration["OpenIdConnect:ClientSecret"];
    options.ResponseType = "code";
    options.SaveTokens = true;
});

// Expose a secure configuration reader for downstream API keys without reflection
builder.Services.AddHttpClient("ExternalService", client =>
{
    // The key should be injected securely and not logged
    var apiKey = builder.Configuration["ExternalService:ApiKey"];
    if (string.IsNullOrEmpty(apiKey))
    {
        throw new InvalidOperationException("ExternalService:ApiKey is not configured.");
    }
    client.DefaultRequestHeaders.Add("X-API-Key", apiKey);
});

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();

In this example, ClientSecret and API keys are read from configuration without being echoed in responses. Ensure that your configuration sources (e.g., appsettings.Development.json) are excluded from deployment and that environment variables are used in production. For additional security, bind secrets to runtime environment variables and avoid storing them in source control.

To prevent data exposure, avoid creating endpoints that return configuration or token details. If you must provide diagnostics, strip sensitive values and enforce strict access controls. For example, do not implement an endpoint like the following:

// Avoid this pattern
[HttpGet("debug")]
public IActionResult Debug()
{
    return Ok(new {
        OidcClientSecret = _config["OpenIdConnect:ClientSecret"],
        ApiKey = _config["ExternalService:ApiKey"]
    });
}

Instead, rely on built-in health checks and monitoring that do not expose secrets. middleBrick’s scans will flag any endpoint that returns keys or secrets; following the above patterns helps ensure that Authentication and Data Exposure checks do not identify leaks. By combining secure secret storage, cautious logging, and restricted configuration endpoints, you reduce the risk of API key exposure in OIDC-enabled ASP.NET applications.

Frequently Asked Questions

Can an exposed API key be used even if OIDC authentication is properly configured?
Yes. API keys and OIDC credentials serve different purposes; an exposed API key can allow direct access to downstream services independently of OIDC authentication, so both must be protected.
Does middleBrick’s scan require authentication to detect API key exposure in ASP.NET OIDC apps?
No. middleBrick performs unauthenticated black-box scans and can identify exposed keys in configuration endpoints, error messages, or logs without requiring credentials.