Broken Authentication in Hanami with Firestore
Broken Authentication in Hanami with Firestore — how this specific combination creates or exposes the vulnerability
Broken Authentication in a Hanami application that uses Google Cloud Firestore typically arises from a mismatch between Hanami’s session handling and Firestore’s permission model. When authentication state is managed in cookies or tokens without verifying ownership of Firestore documents, attackers can manipulate identifiers to access other users’ data or elevate privileges.
Hanami encourages explicit, domain-driven authentication abstractions. If these abstractions do not enforce per-request ownership checks against Firestore document IDs, an authenticated user can modify the document ID in an API request and retrieve or modify another user’s records (a classic Broken Object Level Authorization, or BOLA/IDOR, pattern). For example, an endpoint like /api/users/:user_id/profile that directly maps user_id to a Firestore document path without verifying that the authenticated subject owns that ID allows horizontal privilege escalation.
Firestore security rules are not a substitute for application-level authorization. Rules can restrict read/write by UID, but if Hanami does not validate that the current user’s identity matches the UID used to construct the document reference, malicious users can simply change the ID in the request and bypass missing checks. This is especially risky when Firestore rules are permissive for development and accidentally left broader in production. Insecure direct object references also combine poorly with missing rate limiting, enabling automated enumeration of user IDs.
Additionally, if Hanami issues Firestore credentials or tokens with excessive scope (for example, a service account key with read/write across collections) and embeds them in client-side code or mobile builds, leaked credentials lead to broad data exposure. Unauthenticated endpoints that expose Firestore-backed resources without verifying identity compound the problem, making user enumeration and account takeover feasible.
Using middleBrick to scan such an API can surface these issues through its Authentication, BOLA/IDOR, and Data Exposure checks, alongside per-category breakdowns and remediation guidance. The scanner cross-references your OpenAPI/Swagger spec with runtime behavior to highlight mismatches between declared authentication and actual Firestore access patterns.
Firestore-Specific Remediation in Hanami — concrete code fixes
Remediation centers on ensuring every Firestore operation is scoped to the authenticated subject and that ownership is verified on each request. Hanami’s use of explicit, immutable value objects for IDs makes it straightforward to enforce this pattern.
First, always resolve the document path from the current user’s identity rather than from user-supplied IDs. For example, given a current user entity with a stable UID, construct the Firestore reference server-side:
# app/actions/profile/show.rb
module Actions
module Profile
class Show
include Hanami::Action
def initialize(user_repo: UserRepository.new, firestore_client: -> { Firestore.new }) # injected for testability
@user_repo = user_repo
@firestore_client = firestore_client
end
def call(params)
user = @user_repo.find_by_id(current_user.id) # current_user from session/auth
raise Hanami::Action::Unauthorized unless user
doc_ref = @firestore_client.call
.collection("users")
.document(user.firestore_uid) # server-side UID, never from params
.collection("profiles")
.document("current")
snapshot = doc_ref.get
if snapshot.exists?
@response.status = 200
@response.body = snapshot.data
else
@response.status = 404
@response.body = { error: "not_found" }.to_json
end
end
end
end
end
Second, enforce ownership at the Firestore rule level with strict UID matching and avoid wildcards that permit broad access:
# firestore.rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid}/profiles/{profile_id} {
allow read, write: if request.auth != null && request.auth.uid == uid && profile_id == "current";
}
match /users/{uid}/private/{documents=**} {
allow read, write: if request.auth != null && request.auth.uid == uid;
}
}
}
Third, avoid embedding service account keys in the client or build environment used by Hanami; instead, rely on server-side Firestore clients with limited IAM roles. If you must use tokens, scope them to least privilege and rotate them regularly. For production, prefer IAM roles over permissive rules and ensure Hanami’s session store is isolated per user.
Finally, integrate middleBrick into your workflow using the CLI to validate fixes: middlebrick scan <url> returns a security risk score and findings mapped to OWASP API Top 10 and compliance frameworks. The Pro plan adds continuous monitoring and CI/CD integration so future regressions are caught before deployment.
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 |