Broken Authentication in Phoenix with Firestore
Broken Authentication in Phoenix with Firestore — how this specific combination creates or exposes the vulnerability
Broken authentication in a Phoenix application using Google Cloud Firestore typically arises when session handling, credential verification, or token validation is implemented inconsistently between the application layer and the data layer. Because Firestore is often used as a backend store for user data, misconfigurations in how Phoenix interacts with Firestore can unintentionally expose authentication weaknesses.
One common pattern is using Firestore to store user credentials or session metadata while relying solely on Phoenix for access control. If Phoenix endpoints do not independently verify the identity of the caller on every request, an attacker can manipulate session identifiers or reuse tokens across users. For example, an endpoint that reads users/{user_id}/sessions/{session_token} without confirming that the authenticated subject matches user_id can enable IDOR via predictable IDs.
Another vector involves Firestore security rules that are permissive by design during rapid prototyping. Rules that allow read or write access based only on request authentication status, without enforcing ownership checks (e.g., request.auth.uid != resource.data.uid), can permit horizontal privilege escalation. Attackers can leverage weak or missing ownership rules to access other users’ documents, especially when indexes or queries expose user collections without proper constraints.
The interaction between Phoenix and Firestore can also amplify issues in token handling. If Phoenix decodes a JWT and then uses the payload to construct Firestore queries without validating claims such as iss, exp, and uid, an attacker can inject a token with a different uid and gain access to another user’s records. This is a form of BOLA (Broken Level Authorization) where the application trusts the client-supplied identifier instead of enforcing server-side ownership checks.
Because middleBrick scans the unauthenticated attack surface, it can detect endpoints where authentication is missing or misaligned with Firestore rules. Findings often highlight weak session management, missing ownership validation, and overly permissive rules that enable unauthorized data access. Remediation involves tightening both Phoenix logic and Firestore rules so that every read and write is verified against the authenticated subject and the principle of least privilege is enforced.
Firestore-Specific Remediation in Phoenix — concrete code fixes
To fix broken authentication when using Firestore in Phoenix, align session and identity management with strict server-side checks. Avoid relying on client-supplied identifiers alone, and enforce ownership at both the application and database rule layers.
1. Validate ownership in Phoenix before Firestore access
For each request that targets a user-specific document, confirm that the authenticated subject matches the document’s owner. Use a plug to load the current user and bind it to the connection.
defmodule MyAppWeb.Plugs.RequireUserOwnership do
import Plug.Conn
alias MyApp.Accounts
def init(opts), do: opts
def call(conn, _opts) do
with %{"uid" => user_id} when not is_nil(user_id) <- fetch_session(conn),
%Firestore.Document{data: %{"uid" => doc_uid}} <- fetch_resource(conn) do
if user_id == doc_uid do
conn
else
send_resp(conn, 403, "Forbidden") |> halt()
end
else
_ -> send_resp(conn, 401, "Unauthorized") |> halt()
end
end
end
This plug ensures that the user ID from the session matches the document’s UID before any Firestore operation proceeds.
2. Use Firestore security rules to enforce ownership
Define rules that require authenticated requests and explicitly validate ownership on reads and writes. Do not rely on request.auth being present without checking the document’s fields.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId}/data/{document=**} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
match /sessions/{sessionId} {
allow read, write: if request.auth != null && request.auth.uid == request.resource.data.user_id;
}
}
}
These rules reject any request where the authenticated UID does not match the document UID, preventing horizontal privilege escalation.
3. Use parameterized queries in Phoenix to avoid injection and enforce scope
When querying Firestore from Phoenix, always scope queries by the authenticated UID and use structured parameters instead of string interpolation.
query = Firestore.where("uid", :==, user_id)
-> Firestore.limit(10)
case Firestore.collection("user_data")
-> query
-> Firestore.get() do
{:ok, docs} -> {:ok, docs}
{:error, reason} -> {:error, reason}
end
This pattern avoids leaking data across users and aligns with the principle of least privilege.
4. Secure token handling and session binding
If using JWTs issued by an identity provider, validate standard claims server-side and bind the token to the Firestore UID. Do not trust the payload’s UID without verifying the token signature and expiry.
defmodule MyAppWeb.Auth do
use Guardian, otp_app: :my_app
def subject_for_token(resource, _claims) do
{:ok, to_string(resource.id)}
end
def resource_from_claims(claims) do
{:ok, %MyApp.Accounts.User{id: claims["sub"]}}
end
end
Combine this with a plug that rechecks ownership on sensitive endpoints to reduce the risk of token replay or misalignment.
middleBrick can surface misaligned authentication flows and overly permissive Firestore rules by correlating runtime requests with spec-defined security schemes. By applying these fixes, you reduce the attack surface for broken authentication and ensure that Firestore access remains tightly coupled with verified identity.
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 |