HIGH bola idorhanamibearer tokens

Bola Idor in Hanami with Bearer Tokens

Bola Idor in Hanami with Bearer Tokens — how this specific combination creates or exposes the vulnerability

Broken Level of Authorization (BOLA) is an API security risk where an attacker can access or modify resources that should be restricted to a different user. In Hanami, a Ruby web framework that emphasizes explicit architecture, BOLA often arises when authorization checks are missing or incorrectly scoped around resource identifiers. When Bearer Tokens are used for authentication, the presence of a valid token does not imply access to every resource; the token must be tied to the correct subject and the application must enforce per-resource ownership or tenant boundaries.

Consider a Hanami endpoint that retrieves a user profile by ID:

GET /api/v1/profiles/123
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidXNlcjEyMyJ9.example

If the endpoint resolves the token to a user identity (e.g., user_id: "user123") but then fetches the profile record by the path parameter (123) without verifying that profile belongs to user123, a BOLA vulnerability exists. The Bearer Token ensures the request is authenticated, but it does not enforce authorization at the resource level. An attacker who knows or guesses another user’s ID (e.g., /profiles/456) can read that profile if the backend does not validate ownership.

Hanami’s explicit routing and use of objects can encourage a pattern where IDs are passed directly to repositories or services. Without an explicit policy check that maps the token’s subject to the requested resource, the unauthenticated attack surface includes logic flaws in authorization. This becomes more impactful when IDs are predictable (sequential integers or UUIDs not namespaced per user) and when the API returns sensitive data such as email, roles, or PII. The scanner categories in middleBrick’s LLM/AI Security and Property Authorization checks are designed to surface such gaps by correlating runtime requests with OpenAPI/Swagger definitions and observed responses, including cross-references between spec definitions and runtime behavior.

In practice, BOLA with Bearer Tokens in Hanami can also compound privilege escalation if token handling is inconsistent across endpoints. For example, an endpoint that mistakenly uses a token to infer an admin flag without verifying scope or tenant can allow horizontal or vertical escalation. Because Hanami apps often rely on domain entities and services, developers must ensure that each service explicitly validates that the authenticated subject (from the token) is authorized for the specific operation and resource, rather than relying on route obscurity or implicit trust in the token alone.

Bearer Tokens-Specific Remediation in Hanami — concrete code fixes

To remediate BOLA when using Bearer Tokens in Hanami, enforce explicit ownership or tenant checks in service objects or operations, and avoid leaking internal IDs that can be traversed without validation. Below are concrete, working examples that demonstrate secure patterns.

1. Map token subject to resource ownership

Decode the token, extract the subject, and use it to scope queries. Never trust the ID from the route alone.

# Gemfile
gem "jwt"

# app/services/profile_finder.rb
require "jwt"

class ProfileFinder
  def initialize(request_headers)
    @request_headers = request_headers
  end

  def call(profile_id)
    token = extract_token
    payload = decode_token(token)
    user_id = payload["sub"] || payload["user_id"]

    # Enforce ownership: only return the profile if it belongs to the token's subject
    profile = ProfileRepository.new.find_by(id: profile_id, user_id: user_id)
    raise Hanami::Repository::NoMatchingTuple.new if profile.nil?
    profile
  end

  private

  def extract_token
    auth_header = @request_headers["Authorization"]
    return nil unless auth_header&&auth_header.start_with?("Bearer ")
    auth_header.split(" ").last
  end

  def decode_token(token)
    # Use your actual secret/key and algorithm
    JWT.decode(token, "your_secret_key", true, { algorithm: "HS256" }).first
  rescue JWT::DecodeError
    raise Hanami::InvalidInput, "Invalid token"
  end
end

# app/controllers/api/profiles/show.rb
module API
  module Profiles
    class Show
      def call(params)
        headers = @request.env["rack.request"] ? @request.env : {} # Hanami provides request env
        finder = ProfileFinder.new(headers)
        profile = finder.call(params["id"])
        { status: 200, body: { id: profile.id, user_id: profile.user_id, email: profile.email } }
      end
    end
  end
end

2. Use explicit policy checks with a permissions service

Introduce a lightweight policy object that receives the token subject and the target resource, and returns authorized or not. This keeps authorization logic testable and explicit.

# app/policies/profile_policy.rb
class ProfilePolicy
  def initialize(user_id, record)
    @user_id = user_id
    @record = record
  end

  def show?
    @record.user_id == @user_id
  end
end

# app/services/profile_policy_service.rb
class ProfilePolicyService
  def self.authorize!(profile_id, token)
    user_id = decode_token(token)["user_id"]
    profile = ProfileRepository.new.find(profile_id)
    raise Hanami::Authorization::NotAuthorized unless ProfilePolicy.new(user_id, profile).show?
  rescue Hanami::Repository::NoMatchingTuple
    raise Hanami::Authorization::NotAuthorized
  end

  def self.decode_token(token)
    JWT.decode(token, "your_secret_key", true, { algorithm: "HS256" }).first
  rescue JWT::DecodeError
    raise Hanami::Authorization::NotAuthorized
  end
end

# app/controllers/api/profiles/show_secure.rb
module API
  module Profiles
    class ShowSecure
      def call(params)
        auth_header = @request.env["HTTP_AUTHORIZATION"]
        token = auth_header&&.start_with?("Bearer ") ? auth_header.split(" ").last : nil
        raise Hanami::Authorization::NotAuthorized unless token

        ProfilePolicyService.authorize!(params["id"], token)
        profile = ProfileRepository.new.find(params["id"])
        { status: 200, body: { id: profile.id, user_id: profile.user_id, email: profile.email } }
      end
    end
  end
end

3. Validate and scope repository queries

Ensure repository methods always include the subject from the token. Avoid “find by ID only” methods in public-facing contexts; prefer scoped finders.

# app/repositories/profile_repository.rb
class ProfileRepository
  def initialize
    @db = DB
  end

  def find_by(id:, user_id:)
    @db["profiles"].where(id: id, user_id: user_id).first
  end

  def all_for_user(user_id)
    @db["profiles"].where(user_id: user_id).to_a
  end
end

# Usage in an operation or controller
# Ensure you pass the decoded user_id from the token every time
profile = ProfileRepository.new.find_by(id: params["id"], user_id: current_user_id)

4. Secure token handling and error handling

Return generic errors for missing or invalid tokens and avoid exposing internal IDs in error messages. Always use HTTPS to protect Bearer Tokens in transit.

# Example HTTP response for unauthorized requests
# Status: 401 Unauthorized
# Body: { "error": "unauthorized" }
# Do not return stack traces or internal IDs in production.

5. API spec and scanning considerations

Keep your OpenAPI/Swagger spec accurate so middleBrick’s cross-reference checks align spec definitions with runtime behavior. Explicitly document that endpoints require a Bearer Token and describe authorization scopes. This helps automated scans correlate authentication mechanisms with expected authorization rules and surface BOLA findings with severity and remediation guidance.

Related CWEs: bolaAuthorization

CWE IDNameSeverity
CWE-250Execution with Unnecessary Privileges HIGH
CWE-639Insecure Direct Object Reference CRITICAL
CWE-732Incorrect Permission Assignment HIGH

Frequently Asked Questions

Does a valid Bearer Token guarantee access to a resource in Hanami?
No. A valid Bearer Token indicates authentication, but authorization must be enforced separately. Always scope queries to the token’s subject (e.g., user_id) and validate ownership or tenant boundaries to prevent BOLA.
How can I test for BOLA in Hanami APIs using Bearer Tokens?
Use tools that correlate OpenAPI/Swagger definitions with runtime requests, such as middleBrick’s Property Authorization and LLM/AI Security checks. These can surface missing ownership checks and provide prioritized findings with severity and remediation guidance.