Broken Authentication in Adonisjs with Firestore
Broken Authentication in Adonisjs with Firestore — how this specific combination creates or exposes the vulnerability
When AdonisJS applications rely on Firestore as the identity and session store, several implementation patterns can weaken authentication. A common root cause is treating Firestore documents as trusted sources of authorization without re-verifying authentication state on each request. Because Firestore security rules operate separately from application logic, rules that are too permissive can allow unauthenticated or unverified clients to read or write user data, effectively bypassing intended access controls.
Session management in AdonisJS often uses JWTs or cookie-based sessions. If tokens or session identifiers are stored insecurely (for example, in client-side storage without HttpOnly and Secure flags) or if the application fails to validate token signatures and expiration on every request, an attacker can reuse captured tokens. Similarly, if the application uses Firestore UID fields directly from client-supplied payloads to look up user documents, an attacker can tamper with identifiers to escalate privileges horizontally or vertically (BOLA/IDOR).
AdonisJS middleware stacks must enforce authentication before route handlers execute. If middleware is misconfigured or omitted for sensitive endpoints (password change, email verification, token refresh), requests may execute without a verified identity context. Because Firestore rules cannot distinguish between intentional application calls and direct client writes, over-reliance on rules for authentication rather than server-side checks creates a gap. For instance, a rule that allows users to update only their own documents is insufficient if the application layer does not validate that the authenticated user ID matches the document being modified.
The combination of AdonisJS routing and Firestore’s realtime, schema-flexible model can also expose metadata that aids attackers. Error messages leaking stack traces or Firestore-specific details can reveal collection structures. If rate limiting is applied at the Firestore rules level rather than at the AdonisJS layer, attackers can perform credential spraying or token enumeration without triggering application-side protections. Inadequate logging in AdonisJS means suspicious authentication events may go unnoticed, reducing the ability to detect brute-force or token replay attacks against Firestore-backed accounts.
Finally, insecure default configurations in AdonisJS projects, such as using development-mode secrets or retaining debug utilities in production, can expose authentication endpoints. If Firestore credentials are embedded in frontend code or environment variables improperly scoped, attackers can gain read/write access to user collections. Continuous monitoring and strict separation of authentication responsibilities between AdonisJS middleware and Firestore rules are essential to prevent broken authentication in this stack.
Firestore-Specific Remediation in Adonisjs — concrete code fixes
Remediation centers on enforcing authentication in AdonisJS before any Firestore interaction and tightening Firestore rules to align with least-privilege principles. Always validate the authenticated user ID server-side and use it to scope Firestore queries rather than accepting identifiers from the client.
Secure authentication guard
Create an AdonisJS middleware that ensures a valid session or JWT exists and attaches the user identity to the request context before handlers run:
// start/hooks.ts
import { Exception } from '@poppinss/utils'
export const authenticate = async (ctx, next) => {
const auth = ctx.auth
if (!auth || !auth.user) {
throw new Exception('Unauthorized', 401, 'E_UNAUTHENTICATED')
}
ctx.authUser = auth.user // normalized user object
await next()
}
Apply this middleware to routes that interact with Firestore user data:
// routes/auth.ts
Route.patch('profile/:profileId', ['auth:api', 'firestore.validateOwnership'], ProfileController.update)
Firestore rule alignment with AdonisJS identity
Rules should reference authenticated UID from request.auth and reject any client-supplied UID in paths. Use getAfter to enforce updates only via server-side logic:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
// Prevent client from changing userId in path
}
match /profiles/{docId} {
allow read: if request.auth != null;
allow write: if request.auth != null && request.auth.uid == request.resource.data.user_id;
}
}
}
Server-side Firestore access in AdonisJS controller
Use the Firebase Admin SDK on the server to avoid trusting client input. Resolve user-specific paths with the authenticated UID, not client-supplied identifiers:
// controllers/ProfileController.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { getFirestore, doc, getDoc, updateDoc } from 'firebase-admin/firestore'
export default class ProfileController {
public async update({ auth, request, response }: HttpContextContract) {
const db = getFirestore()
const userId = auth.user!.uid // from authenticated guard
const profileRef = doc(db, 'users', userId, 'profile', 'public')
const snapshot = await getDoc(profileRef)
if (!snapshot.exists()) {
return response.notFound({ message: 'Profile not found' })
}
// Apply only validated, server-side transformations
await updateDoc(profileRef, { bio: request.input('bio') })
return response.ok({ updated: true })
}
}
Token and session hardening
Ensure JWTs or session cookies are HttpOnly, Secure, and SameSite strict. Validate signatures and claims on each request and rotate secrets regularly. Avoid storing sensitive identifiers in localStorage to mitigate XSS-driven token theft that could lead to Firestore data exposure.
Monitoring and least privilege
Instrument AdonisJS logs to record authentication successes and failures alongside Firestore rule denials. Regularly audit Firestore rules to ensure they do not grant write access based solely on request.auth presence without UID matching. Combine AdonisJS middleware checks with tightly scoped Firestore rules for defense-in-depth.
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 |