Api Rate Abuse in Hanami with Bearer Tokens
Api Rate Abuse in Hanami with Bearer Tokens — how this combination creates or exposes the vulnerability
Rate abuse in a Hanami API when Bearer tokens are used centers on how per-client limits are enforced. Without strong per-token tracking, an attacker who obtains a single token can issue many requests in a short window, exhausting the intended quota for that token and potentially impacting other tenants that share backend resources. Hanami applications often expose endpoints that rely on token-based authentication, and if rate limiting is applied only at the API gateway or reverse proxy without considering the token value, the protection is incomplete.
Consider an endpoint that returns sensitive account information. If the route does not incorporate the token identity into the rate key, a shared limit might apply globally rather than per token. An attacker can repeatedly call the endpoint with a stolen Bearer token, triggering HTTP 429 responses only after the global limit is breached, while the token’s specific quota remains unused. This becomes especially problematic when the token is scoped to a higher-tier plan that permits more requests; abuse of that elevated allowance can mask lateral movement or data scraping.
Another scenario involves token issuance patterns. If your Hanami service issues short-lived bearer tokens without binding them to a client identity or a strict request count, an attacker who intercepts a token can perform burst attacks before expiration. Inadequate logging of token usage alongside request paths also hampers detection, because standard access logs might not clearly correlate token IDs with per-minute request counts. Without per-token aggregation in logs or rate counters, abuse can persist unnoticed until downstream effects such as elevated latency or error spikes appear.
The interaction with scopes and roles compounds the risk. A token with scopes like read:account and read:reports might be allowed higher request rates than a token with only read:public. If the rate policy is not enforced consistently across all layers—application, database, and external APIs—an attacker can pivot to endpoints that have looser limits. For example, a token used for read-only analytics could be hammered to extract large data sets, especially if the endpoint lacks additional context checks like referer or origin validation.
To detect this class of issue, you can run a scan that exercises the same endpoint with repeated calls using the same Bearer token and observe whether rate enforcement is applied per token or only per IP. middleBrick’s checks include unauthenticated probing as well as authenticated flows where credentials are supplied, and it evaluates the API definition (OpenAPI 2.0/3.0/3.1 with full $ref resolution) against runtime behavior. The tool can surface findings such as missing per-token rate limits, weak burst thresholds, and inconsistent enforcement that maps to OWASP API Top 10 and relevant compliance frameworks.
Bearer Tokens-Specific Remediation in Hanami — concrete code fixes
Remediation focuses on tying rate limits to the token identity and ensuring consistent enforcement across layers. In a Hanami application, you typically have a middleware or service object that authenticates the token and makes it available in the request environment. Use that identity to build a granular rate key and enforce limits close to the route handler.
Example: a Rack-based rate middleware that uses the Bearer token as part of the key. This snippet demonstrates storing a counter in a Redis-like store with a sliding window keyed by token and endpoint path.
require "redis"
class TokenRateLimiter
def initialize(app, redis_url = "redis://localhost:6379/0")
@app = app
@redis = Redis.connect(url: redis_url)
end
def call(env)
token = extract_bearer_token(env)
if token
path = env["PATH_INFO"]
key = "rate_limit:#{token}:#{path}"
limit = per_minute_limit_for(token, path)
current = @redis.incr(key)
if current == 1
@redis.expire(key, 60)
end
if current > limit
return [429, { "Content-Type" => "application/json" }, [{ error: "rate_limit_exceeded" }.to_json]]
end
end
@app.call(env)
end
private
def extract_bearer_token(env)
auth = env["HTTP_AUTHORIZATION"]
return nil unless auth&.start_with?("Bearer ")
auth.split(" ", 2).last
end
def per_minute_limit_for(token, path)
# Map token scopes or roles to limits
case token_scope(token)
when "admin"
300
when "premium"
120
else
60
end
end
def token_scope(token)
# Stub: fetch token metadata from your auth service
# Return scope string used for limit mapping
"standard"
end
end
# In your Hanami app boot sequence, wrap the app with the middleware
use TokenRateLimiter
run MyApp::Router
The above code ensures that each Bearer token has its own counter per path, preventing one token from consuming another token’s quota. It also maps token scopes to different limits, addressing privilege-based abuse. In production, you should use a distributed store like Redis and consider sliding windows or token-bucket algorithms to smooth bursts while respecting overall ceilings.
Additionally, enrich logs with the token identifier to simplify investigations. In a Hanami action or endpoint, you can include the token hash (never log the raw token) in structured logs:
class AccountShow
def call(params)
token = env["token"] # extracted earlier
logger.info({
event: "account_show",
token_hash: Digest::SHA256.hexdigest(token),
path: env["PATH_INFO"],
ip: env["REMOTE_ADDR"]
})
# proceed with business logic
end
end
For continuous monitoring, the Pro plan’s dashboard can track per-token request rates and alert when a token approaches its limit. The CLI can be used in CI to assert that your OpenAPI spec documents per-token rate limits for authenticated routes, and the GitHub Action can fail a build if a new endpoint lacks token-aware throttling rules.