Broken Authentication in Hanami with Bearer Tokens
Broken Authentication in Hanami with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Hanami is a Ruby web framework that encourages explicit, layered security design. When Bearer Tokens are used for API authentication, the risk of broken authentication typically arises from how tokens are generated, stored, transmitted, and validated. A misconfigured Hanami application can expose endpoints to token prediction, leakage, or replay, leading to unauthorized access across user boundaries.
One common pattern is using a static or weakly-entropy token stored in environment variables and passed via the Authorization header as Authorization: Bearer <token>. If the token is shared across users or services, a BOLA/IDOR (Broken Level of Authorization/Insecure Direct Object Reference) issue can occur when one user can access another user’s resources simply by changing an identifier in the request, because the backend does not validate token-to-identity mapping on each request. For example, an endpoint like /api/v1/users/:id/profile that trusts the token but does not verify that the token’s associated subject matches :id can be abused.
Transport-layer weaknesses also contribute. If HTTPS is not enforced in production, Bearer Tokens can be intercepted via man-in-the-middle attacks. Hanami applications that terminate TLS at a load balancer but do not enforce strict forwarding headers (e.g., x-forwarded-proto) may allow token transmission over plaintext HTTP internally. Additionally, insufficient token binding means that stolen tokens remain valid until expiration, and there is no mechanism to revoke them per-session. Logging of Authorization headers without redaction can lead to accidental token exposure in application logs, creating a data exposure vector.
From a scanning perspective, middleBrick’s Authentication and BOLA/IDOR checks, run in parallel with Data Exposure and Encryption checks, can surface these weaknesses during an unauthenticated scan of a Hanami API. The scanner inspects OpenAPI/Swagger specifications (2.0, 3.0, 3.1) with full $ref resolution and cross-references spec definitions with runtime behavior. For instance, if the spec defines a Bearer security scheme but the implementation lacks scope validation or proper token introspection, the scan will flag findings mapped to frameworks such as OWASP API Top 10 and SOC2. Continuous monitoring under the Pro plan can detect regressions, while the CLI allows teams to integrate checks into scripts and fail builds when risk thresholds are exceeded.
Real-world attack patterns include token replay via intercepted requests, privilege escalation through tampered token payloads when using unsigned or weakly signed tokens, and SSRF-induced token leakage from internal services that expose metadata. Proper mitigation requires strict transport security, precise scoping, and validation of token claims against the identity of the resource being accessed.
Bearer Tokens-Specific Remediation in Hanami — concrete code fixes
Remediation focuses on ensuring each Bearer token is unique per user or service, bound to the correct identity, and validated on every request. Below are concrete patterns and code examples for a Hanami application using hanami-controller and hanami-router.
1. Use a secure token generation strategy and bind it to a user identity. Avoid static tokens. Instead, issue a cryptographically random token and store a namespaced version in the database alongside the user id.
# config/initializers/token_generator.rb
require 'securerandom'
module TokenGenerator
def self.secure_token
SecureRandom.urlsafe_base64(32)
end
end
2. Store tokens with user association and a scope. In your entity and repository:
# lib/hanami/entities/user_token.rb
UserToken = Struct.new(:id, :user_id, :token_hash, :scopes, :expires_at) do
def self.digest(token)
Digest::SHA256.hexdigest(token)
end
end
# lib/hanami/repositories/user_tokens.rb
class UserTokens
def initialize(relation: Hanami::Repository[Hanami::Relation.new(:users)])
@users = relation
end
def create_token(user_id, raw_token, scopes)
token_hash = UserToken.digest(raw_token)
# persist token_hash, not raw token
user_tokens_repo.create(user_id: user_id, token_hash: token_hash, scopes: scopes, expires_at: Time.now + 3600)
end
def find_by_token(raw_token)
token_hash = UserToken.digest(raw_token)
user_tokens_repo.find_by(token_hash: token_hash)
end
end
3. In the controller, validate token ownership before accessing a resource. Ensure the token’s associated user id matches the requested resource id:
# web/controllers/api/profiles/show.rb
module Api::Controllers::Profiles
class Show
include Api::Action
def initialize(user_tokens_repo: UserTokens.new)
@user_tokens_repo = user_tokens_repo
end
def call(params)
token = params['HTTP_AUTHORIZATION']&.split(' ')&.last
halt 401, { error: 'missing_token' }.to_json unless token
record = @user_tokens_repo.find_by_token(token)
halt 404, { error: 'token_not_found' }.to_json unless record
# BOLA protection: ensure the token belongs to the user being accessed
requested_id = params[:id].to_i
halt 403, { error: 'forbidden' }.to_json unless record.user_id == requested_id
# proceed with safe response
{ user_id: record.user_id, scopes: record.scopes }.to_json
end
end
end
4. Enforce HTTPS and avoid logging Authorization headers. In your Hanami configuration, set config.force_ssl = true in production and ensure reverse proxies preserve the correct protocol. Add a request filter to scrub sensitive headers from logs:
# lib/hanami/logging_filter.rb
class LoggingFilter
def self.filter_headers(headers)
headers.except('HTTP_AUTHORIZATION', 'HTTP_COOKIE')
end
end
5. Use short-lived tokens and implement revocation. Consider storing a token version on the user record and incrementing it on logout or password change; validate the version during token lookup to effectively revoke issued tokens.
By combining strong token generation, binding tokens to identities, enforcing ownership checks, and protecting transport and logs, Hanami APIs using Bearer Tokens can mitigate authentication and authorization flaws that would otherwise be exposed via BOLA/IDOR or data exposure pathways.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |