Broken Authentication in Spring Boot with Firestore
Broken Authentication in Spring Boot with Firestore — how this specific combination creates or exposes the vulnerability
Broken Authentication occurs when application functions related to authentication and session management are implemented incorrectly, allowing attackers to compromise passwords, keys, or session tokens. In a Spring Boot application using Google Cloud Firestore as the user store, the risk emerges from how identity data is read, written, and validated. Firestore is a NoSQL document database; if security rules are misconfigured or if the application does not enforce strong checks before trusting Firestore query results, attackers can manipulate identifiers to access or escalate privileges across user boundaries.
Common patterns that lead to Broken Authentication in this stack include:
- Insecure direct object references (IDOR) when using predictable document IDs (e.g., user UIDs) without verifying that the requesting user owns that document.
- Weak or missing verification of authentication state (e.g., relying only on a JWT in a header without validating signature, issuer, and audience, or without cross-checking Firestore user records).
- Overly permissive Firestore security rules that allow read or write access to user collections based only on request.path.uid without ensuring the authenticated principal matches the document ID.
- Improper session handling, such as storing session identifiers in insecure cookies or failing to rotate tokens after login or privilege changes.
An example attack scenario: an authenticated user changes the user ID in the request from /users/abc123 to /users/def456. If the backend queries Firestore for that document without confirming that the authenticated user’s UID matches def456, the attacker can view or modify another user’s profile or settings. Similarly, if Firestore rules allow read, write: if request.auth != null without scoping to the user’s own document, any authenticated user can read all user documents.
Spring Boot applications must couple Firestore client usage with explicit ownership checks and robust rule design. Relying solely on Firestore rules is not sufficient; the application layer must validate that the requesting user matches the resource owner, using claims from an authenticated session (e.g., Firebase ID token) and verifying against Firestore data before performing operations.
Firestore-Specific Remediation in Spring Boot — concrete code fixes
Remediation centers on strict ownership verification, secure token handling, and least-privilege Firestore rules. Always validate on the server that the authenticated user’s UID matches the requested document ID, and enforce this principle in both code and security rules.
Example secure Spring Boot controller using the Firebase Admin SDK:
@RestController
@RequestMapping("/api/users")
public class UserController {
private final FirebaseFirestore db;
public UserController() {
this.db = FirebaseFirestore.getInstance();
}
@GetMapping("/me")
public ResponseEntity getMyProfile(@RequestHeader("Authorization") String authHeader) {
String idToken = authHeader.startsWith("Bearer ") ? authHeader.substring(7) : authHeader;
FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
String uid = decodedToken.getUid();
DocumentReference userRef = db.collection("users").document(uid);
ApiFuture future = userRef.get();
DocumentSnapshot snapshot = future.get();
if (!snapshot.exists()) {
return ResponseEntity.notFound().build();
}
UserProfile profile = snapshot.toObject(UserProfile.class);
return ResponseEntity.ok(profile);
}
@PatchMapping("/me")
public ResponseEntity updateMyProfile(@RequestBody UserProfileUpdate update,
@RequestHeader("Authorization") String authHeader) {
String idToken = authHeader.startsWith("Bearer ") ? authHeader.substring(7) : authHeader;
FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
String uid = decodedToken.getUid();
DocumentReference userRef = db.collection("users").document(uid);
// Explicitly set only allowed fields to prevent mass assignment
Map updates = new HashMap<>();
updates.put("displayName", update.displayName());
updates.put("email", update.email());
userRef.update(updates);
return ResponseEntity.ok().build();
}
}
Key points in the code:
- The UID used for the Firestore document path is derived from the verified ID token, not from user input.
- The document path is constructed from the trusted UID, and no user-supplied identifier is used to select the document.
- Updates are limited to specific fields to prevent unintended data modification (mass assignment protection).
Complementary Firestore security rules (Firebase Realtime Database rules do not apply to Firestore; here are Firestore rules) to enforce ownership at the database level:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
Additional remediation practices:
- Use short-lived ID tokens and refresh tokens securely; do not store sensitive data in client-side tokens.
- Apply the principle of least privilege to the service account used by the Spring Boot app: limit Firestore access to only the collections and operations required.
- Log authentication events and failed document access attempts for anomaly detection, but do not log raw credentials or sensitive PII.
- Consider using custom claims for role-based access control and validate roles both in code and rules, but always pair claims with document-level ownership checks.
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 |