HIGH api rate abusephoenixopenid connect

Api Rate Abuse in Phoenix with Openid Connect

Api Rate Abuse in Phoenix with Openid Connect — how this specific combination creates or exposes the vulnerability

API rate abuse occurs when an attacker sends excessive requests to an endpoint, degrading availability or enabling enumeration. In a Phoenix application using OpenID Connect for authentication, the combination of token validation, user session handling, and public endpoints can create conditions where rate limits are either missing or bypassed.

Phoenix applications often expose routes that perform token introspection, user discovery, or dynamic configuration lookup based on OpenID Connect claims. When these routes lack request throttling, an attacker can repeatedly call them with different tokens or subjects to trigger expensive operations such as JWT validation, database lookups, or external HTTP calls to the OpenID Provider metadata or JWKS endpoint.

OpenID Connect introduces identifiable context like subject (sub) and issuer (iss) that can be used to target specific users. Without rate limiting tied to these claims, an attacker can probe token validity or harvest user information by observing rate-based differences in response codes or timing. For example, sending many authorization requests with malformed tokens may reveal whether a token is revoked or expired based on error response variance.

The public endpoints defined in the OpenID Connect discovery document (e.g., /.well-known/openid-configuration) and the JWKS URI are typically unauthenticated and cached at the application or CDN layer. If these endpoints are not explicitly rate-limited, an attacker can download the configuration and keys repeatedly, increasing load on the authentication service and potentially aiding further attacks such as token signature validation bypass attempts.

In Phoenix, routes that call Guardian.decode_token or perform database queries based on sub are especially sensitive. Without tying rate limits to the authenticated subject or issuer, an attacker can saturate the backend by spinning up many sessions or injecting tokens that trigger repeated verification logic.

To detect this using middleBrick, you can submit your Phoenix endpoint URL for an unauthenticated scan. The tool checks whether rate limiting is applied to authentication-sensitive paths and flags missing controls as high-severity findings, referencing patterns seen in OAuth 2.0 and OpenID Connect abuse cases.

Openid Connect-Specific Remediation in Phoenix — concrete code fixes

Remediation focuses on applying rate limits at the appropriate layer and scope, using OpenID Connect context such as issuer and subject to make limits meaningful. Below are targeted strategies and code examples for Phoenix.

1. Rate limit token validation and user info endpoints

Apply rate limits to endpoints that validate tokens or fetch user info, scoped by issuer and subject where available. Use a composite key to avoid unfair throttling across unrelated issuers.

defmodule MyAppWeb.AuthPlug do
  import Plug.Conn
  alias MyApp.RateLimiter

  def init(opts), do: opts

  def call(conn, _opts) do
    case get_auth_context(conn) do
      {:ok, %{iss: iss, sub: sub}} ->
        key = "#{iss}:#{sub}"
        if RateLimiter.exceeded?(key, limit: 60, interval: 60) do
          conn
          |> put_status(429)
          |> json(%{error: "rate_limit_exceeded"})
          |> halt()
        else
          conn
        end
      _ ->
        conn
    end
  end

  defp get_auth_context(conn) do
    with [token] <- get_req_header(conn, "authorization"),
         {:ok, claims} <- MyApp.Auth.verify(token) do
      {:ok, %{iss: claims["iss"], sub: claims["sub"]}}
    else
      _ -> {:error, :invalid}
    end
  end
end

This plug checks a composite key composed of the OpenID Connect issuer and subject, enforcing a limit of 60 requests per minute per authenticated user-issuer pair.

2. Rate limit discovery and JWKS endpoints

Apply conservative rate limits to unauthenticated discovery and key endpoints. Use IP-based limits as a baseline when subject-level context is unavailable.

defmodule MyAppWeb.OpenIdPlug do
  import Plug.Conn

  def init(opts), do: opts

  def call(conn, _opts) do
    ip = peer_ip(conn)
    key = "ip:#{ip}"
    if RateLimiter.exceeded?(key, limit: 30, interval: 60) do
      conn
      |> put_status(429)
      |> json(%{error: "rate_limit_exceeded"})
      |> halt()
    else
      conn
    end
  end

  defp peer_ip(conn) do
    case List.first(get_req_header(conn, "x-forwarded-for")) do
      nil -> conn.remote_ip |> :inet.ntoa() |> to_string()
      forwarded -> forwarded
    end
  end
end

Use this plug on routes like /.well-known/openid-configuration and /.well-known/jwks.json to prevent excessive metadata fetches and potential enumeration.

3. Token revocation and introspection rate limiting

If your Phoenix app exposes revocation or introspection endpoints, scope limits by token identifiers or client IDs to prevent targeted abuse. Combine with short TTL caches to reduce backend load.

defmodule MyAppWeb.IntrospectPlug do
  import Plug.Conn

  def init(opts), do: opts

  def call(conn, _opts) do
    with [token] <- get_req_header(conn, "authorization"),
         {:ok, %{sub: sub, iss: iss}} <- extract_claims(conn) do
      key = "introspect:#{iss}:#{sub}"
      if RateLimiter.exceeded?(key, limit: 30, interval: 60) do
        conn
        |> put_status(429)
        |> json(%{error: "rate_limit_exceeded"})
        |> halt()
      else
        conn
      end
    else
      _ -> conn
    end
  end
end

Apply these plugs in your router to protect sensitive authentication flows while preserving usability for legitimate clients.

Frequently Asked Questions

How does middleBrick detect missing rate limiting in OpenID Connect flows?
middleBrick runs unauthenticated checks against your Phoenix endpoints, looking for missing rate limit controls on authentication-sensitive paths such as token validation, user info, discovery, and JWKS endpoints. It flags endpoints that do not enforce throttling and references OpenID Connect-specific abuse patterns.
Can rate limiting be scoped to issuer and subject in Phoenix using OpenID Connect?
Yes. You can scope rate limits using the iss and sub claims from validated tokens. By creating a composite key such as iss:sub, you ensure that limits apply per authenticated user-issuer pair, reducing collateral impact and improving detection of targeted abuse.