HIGH api key exposurefastapiopenid connect

Api Key Exposure in Fastapi with Openid Connect

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

When an API built with Fastapi uses OpenID Connect (OIDC) for authentication but also exposes or mishandles API keys, the combined pattern can inadvertently create a path for credential exposure. This typically occurs when API keys are used as bearer tokens for certain endpoints while OIDC tokens handle others, and safeguards such as strict scope validation, audience checks, and token binding are not consistently enforced.

In a Fastapi application, developers often integrate an OIDC provider (e.g., Auth0, Okta, Keycloak) using packages like python-jose, passlib, and an OIDC client library. If API keys are accepted in headers, query parameters, or cookies without proper isolation from the OIDC flow, an attacker who can read logs, error messages, or network traffic may observe both key material and ID tokens. For example, returning raw keys in error responses or embedding them in frontend JavaScript allows leakage alongside ID token claims, making cross-context abuse possible.

Another common issue is inconsistent audience and issuer validation. Fastapi routes that rely solely on the presence of an OIDC access token without verifying the aud claim can accept tokens intended for other services. If such a route also accepts an API key to escalate permissions, an attacker may supply a valid but unintended ID token alongside a captured API key, bypassing authorization logic that assumes one credential type per request.

Consider an endpoint that accepts both an Authorization header with an OIDC bearer token and an X-API-Key header for legacy services. If the API key is rotated infrequently and lacks binding to the authenticated subject, a leaked key can be reused with a valid OIDC token from a different context. This combination may expose sensitive data or allow privilege escalation if the API key grants broader access than the token’s scopes.

Specification and implementation details matter. In OIDC flows such as Authorization Code with PKCE, tokens are issued with specific claims including issuer (iss), audience (aud), scopes, and subject (sub). Fastapi must validate these claims rigorously and avoid mixing API key material into contexts where token introspection or JWT validation might be bypassed. For instance, accepting an API key in a header without verifying the corresponding OIDC token’s validity can lead to unauthenticated access paths that are difficult to detect through logging alone.

Operational practices also contribute to exposure. If API keys are stored in environment variables that are accidentally printed in structured logs alongside OIDC debug information, or if OpenAPI documentation reveals key locations, the attack surface grows. MiddleBrick’s scans detect such risky patterns by correlating endpoint behaviors with authentication mechanisms and data exposure checks, highlighting places where credentials may be reflected in responses or improperly constrained.

Openid Connect-Specific Remediation in Fastapi — concrete code fixes

To reduce the risk of API key exposure when using OpenID Connect in Fastapi, apply strict validation, separation of concerns, and secure coding patterns. The following examples demonstrate a hardened approach that validates OIDC tokens, avoids mixing API keys with identity tokens, and enforces least privilege.

1. Validate OIDC tokens thoroughly. Verify issuer, audience, expiration, and scopes on every request. Do not rely solely on the presence of a token.

from fastapi import Fastapi, Depends, HTTPException, Security, Header
from jose import jwt, JWTError
from pydantic import BaseModel
import os

app = Fastapi()

OIDC_ISSUER = os.getenv("OIDC_ISSUER")
OIDC_AUDIENCE = os.getenv("OIDC_AUDIENCE")
JWKS_URI = os.getenv("JWKS_URI")

class TokenPayload(BaseModel):
    sub: str
    aud: str
    iss: str
    exp: int
    scopes: list[str]

def verify_token(token: str) -> TokenPayload:
    # In production, use a JWKS client to fetch keys from JWKS_URI
    # This example uses a static key for simplicity
    key = os.getenv("OIDC_SIGNING_KEY")
    try:
        claims = jwt.decode(token, key, algorithms=["RS256"], audience=OIDC_AUDIENCE, issuer=OIDC_ISSUER)
        return TokenPayload(**claims)
    except JWTError as e:
        raise HTTPException(status_code=401, detail=f"Invalid token: {e}")

async def get_current_user(token: str = Security(oauth2_scheme)):
    return verify_token(token)

2. Separate API key usage from identity tokens. If API keys are required, treat them as a distinct credential and validate them independently of the OIDC context. Avoid returning API keys in responses or logs that also contain user identity information.

from fastapi import Security
from typing import Optional

API_KEYS = {"service-account-123": {"scopes": ["read:data", "write:data"]}}

async def validate_api_key(key: Optional[str] = Header(None)):
    if not key or key not in API_KEYS:
        raise HTTPException(status_code=403, detail="Invalid API key")
    return API_KEYS[key]

3. Enforce scope and audience checks on each route. Do not assume a token with a given scope is authorized for an operation that also requires an API key. Use dependency injection to combine checks explicitly when both are required.

from fastapi import Depends

def require_scopes(required: set[str]):
    def inner(token: TokenPayload = Depends(get_current_user)):
        if not required.issubset(set(token.scopes)):
            raise HTTPException(status_code=403, detail="Insufficient scopes")
        return token
    return inner

@app.get("/data")
async def read_data(
    user: TokenPayload = Depends(require_scopes({"read:data"})),
    api_key: dict = Security(validate_api_key)
):
    return {"user": user.sub, "api_key_scope": api_key["scopes"]}

4. Rotate and isolate keys. Use short-lived API keys where possible and avoid embedding them in frontend code. Bind keys to specific OIDC subjects or client IDs when feasible, and monitor usage for anomalies that suggest leakage.

5. Secure logging and error handling. Ensure that neither API keys nor sensitive OIDC claims appear in logs, trace IDs, or error messages returned to clients. Use structured logging that redacts sensitive fields.

6. Leverage MiddleBrick for continuous validation. Add the GitHub Action to your CI/CD pipeline to fail builds if new endpoints introduce risky combinations of authentication mechanisms. Use the Web Dashboard to track security scores over time and remediate findings before deployment.

By strictly validating OIDC tokens, isolating API key usage, and applying layered checks, you reduce the likelihood that a leaked key or token will lead to broader compromise. These practices align with OWASP API Top 10 authentication and authorization failures and help maintain a robust security posture.

Frequently Asked Questions

How can I ensure API keys and OIDC tokens are never logged together in Fastapi?
Configure structured logging to redact or omit sensitive fields. In Fastapi, use a custom logger that strips API key headers and OIDC token claims from log payloads, and avoid printing request objects that may contain both credential types.
Does MiddleBrick detect API key exposure risks when OpenID Connect is in use?
Yes. MiddleBrick runs parallel security checks including Data Exposure and Authentication. It correlates findings across OIDC token handling and API key usage patterns, surfacing risky combinations and providing remediation guidance without accessing or storing your credentials.