Skip to content

Secure Fairbase - #12

Merged
Sazwanismail merged 1 commit into
mainfrom
Sazwanismail-patch-2
Oct 17, 2025
Merged

Secure Fairbase#12
Sazwanismail merged 1 commit into
mainfrom
Sazwanismail-patch-2

Conversation

@Sazwanismail

@SazwanismailSazwanismail commented Oct 17, 2025

Copy link
Copy Markdown
Owner

User description

I'll provide you with comprehensive Firebase security implementation guidance. Here's a detailed security setup:

1. Firebase Security Rules & Configuration

Firebase Security Rules (firebase.json)

{
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"storage": {
"rules": "storage.rules"
},
"hosting": {
"public": "public",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"headers": [
{
"source": "**",
"headers": [
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-XSS-Protection",
"value": "1; mode=block"
},
{
"key": "Strict-Transport-Security",
"value": "max-age=31536000; includeSubDomains"
}
]
}
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"emulators": {
"auth": {
"port": 9099
},
"firestore": {
"port": 8080
},
"storage": {
"port": 9199
},
"ui": {
"enabled": true
}
}
}

2. Firestore Security Rules

firestore.rules

rules_version='2';servicecloud.firestore{match/databases/{database}/documents{// Global read/write control - adjust as neededmatch/{document=**}{
allow read,write: ifrequest.auth!=null;}// Users can only access their own user datamatch/users/{userId}{
allow read,write: ifrequest.auth!=null&&request.auth.uid==userId;allowcreate: ifrequest.auth!=null&&request.auth.uid==userId&&request.resource.data.keys().hasAll(['email','createdAt'])&&request.resource.data.emailisstring&&request.resource.data.createdAtistimestamp;}// Posts collection - users can read all, but only write their ownmatch/posts/{postId}{allowread: ifrequest.auth!=null;allowcreate: ifrequest.auth!=null&&request.auth.uid==request.resource.data.authorId&&request.resource.data.keys().hasAll(['title','content','createdAt'])&&request.resource.data.titleisstring&&request.resource.data.contentisstring&&request.resource.data.createdAtistimestamp;allowupdate,delete: ifrequest.auth!=null&&request.auth.uid==resource.data.authorId;}// Comments - users can read all, but only write their ownmatch/posts/{postId}/comments/{commentId}{allowread: ifrequest.auth!=null;allowcreate: ifrequest.auth!=null&&request.auth.uid==request.resource.data.authorId&&request.resource.data.keys().hasAll(['content','createdAt'])&&request.resource.data.contentisstring&&request.resource.data.createdAtistimestamp;allowupdate,delete: ifrequest.auth!=null&&request.auth.uid==resource.data.authorId;}// Admin role check functionfunctionisAdmin(){returnrequest.auth.token.admin==true;}// Admin-only collectionsmatch/admin/{document=**}{
allow read,write: ifisAdmin();}// Audit trail - read only for adminsmatch/audit/{document=**}{allowread: ifisAdmin();allowwrite: ifrequest.auth!=null;}}}

3. Firebase Storage Security Rules

storage.rules

rules_version='2';servicefirebase.storage{match/b/{bucket}/o{// Users can only upload to their own foldermatch/users/{userId}/{allPaths=**}{allowread: ifrequest.auth!=null;allowwrite: ifrequest.auth!=null&&request.auth.uid==userId;}// Profile pictures - users can read all, but only write their ownmatch/profile_pictures/{userId}{allowread: ifrequest.auth!=null;allowwrite: ifrequest.auth!=null&&request.auth.uid==userId;}// Post images - readable by all authenticated usersmatch/post_images/{postId}/{imageId}{allowread: ifrequest.auth!=null;allowwrite: ifrequest.auth!=null&&exists(/databases/$(database)/documents/posts/$(postId))&&get(/databases/$(database)/documents/posts/$(postId)).data.authorId==request.auth.uid;}// Public read-only filesmatch/public/{allPaths=**}{allowread: iftrue;allowwrite: ifrequest.auth!=null&&isAdmin();}functionisAdmin(){returnrequest.auth.token.admin==true;}}}

4. Firebase Authentication Security

Security Configuration

// firebase-auth-security.jsimport{initializeApp}from'firebase/app';import{getAuth,createUserWithEmailAndPassword,signInWithEmailAndPassword,signOut,updateProfile,sendEmailVerification,sendPasswordResetEmail,setPersistence,browserSessionPersistence,browserLocalPersistence,onAuthStateChanged}from'firebase/auth';constfirebaseConfig={apiKey: process.env.REACT_APP_FIREBASE_API_KEY,authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,appId: process.env.REACT_APP_FIREBASE_APP_ID};constapp=initializeApp(firebaseConfig);constauth=getAuth(app);classFirebaseAuthSecurity{constructor(){this.auth=auth;this.setupSecurityPolicies();}setupSecurityPolicies(){// Set session persistence based on user preferencesetPersistence(this.auth,browserLocalPersistence);// Monitor auth state for securityonAuthStateChanged(this.auth,(user)=>{if(user){this.logSecurityEvent('user_signed_in',user.uid);this.validateUserSession(user);}else{this.logSecurityEvent('user_signed_out');}});}asyncvalidateUserSession(user){// Check if email is verifiedif(!user.emailVerified){awaitsendEmailVerification(user);thrownewError('Please verify your email before proceeding');}// Check if token is recent (less than 1 hour old)consttokenTime=user.metadata.lastSignInTime;constcurrentTime=newDate();consttimeDiff=(currentTime-newDate(tokenTime))/(1000*60*60);if(timeDiff>24){awaitthis.auth.signOut();thrownewError('Session expired. Please sign in again.');}}asyncsecureSignUp(email,password,displayName){try{// Validate password strengththis.validatePassword(password);constuserCredential=awaitcreateUserWithEmailAndPassword(this.auth,email,password);// Update profileawaitupdateProfile(userCredential.user,{displayName: displayName});// Send email verificationawaitsendEmailVerification(userCredential.user);// Log security eventthis.logSecurityEvent('user_registered',userCredential.user.uid);returnuserCredential;}catch(error){this.logSecurityEvent('registration_failed',null,error.message);throwerror;}}asyncsecureSignIn(email,password){try{constuserCredential=awaitsignInWithEmailAndPassword(this.auth,email,password);// Validate sessionawaitthis.validateUserSession(userCredential.user);this.logSecurityEvent('login_success',userCredential.user.uid);returnuserCredential;}catch(error){this.logSecurityEvent('login_failed',null,error.message);throwerror;}}validatePassword(password){constminLength=8;consthasUpperCase=/[A-Z]/.test(password);consthasLowerCase=/[a-z]/.test(password);consthasNumbers=/\d/.test(password);consthasSpecialChar=/[!@#$%^&*(),.?":{}|<>]/.test(password);if(password.length<minLength){thrownewError('Password must be at least 8 characters long');}if(!hasUpperCase){thrownewError('Password must contain at least one uppercase letter');}if(!hasLowerCase){thrownewError('Password must contain at least one lowercase letter');}if(!hasNumbers){thrownewError('Password must contain at least one number');}if(!hasSpecialChar){thrownewError('Password must contain at least one special character');}}asynclogSecurityEvent(eventType,userId=null,details=null){// Log to Firestore for audit trailconstsecurityLog={
eventType,
userId,timestamp: newDate(),userAgent: navigator.userAgent,ipAddress: awaitthis.getClientIP(),
details
};// In a real app, you'd write this to Firestoreconsole.log('Security Event:',securityLog);}asyncgetClientIP(){// This would typically be handled by a cloud function// that can see the real IP addressreturn'client-ip-not-available-in-client';}}exportdefaultFirebaseAuthSecurity;

5. Firebase App Check Implementation

// firebase-app-check.jsimport{initializeAppCheck,ReCaptchaV3Provider}from'firebase/app-check';constappCheck=initializeAppCheck(app,{provider: newReCaptchaV3Provider('your-recaptcha-v3-site-key'),isTokenAutoRefreshEnabled: true});

6. Firebase Security Functions

Cloud Functions for Security

// functions/security.jsconstfunctions=require('firebase-functions');constadmin=require('firebase-admin');admin.initializeApp();// Security: Monitor for suspicious activitiesexports.monitorSuspiciousActivities=functions.firestore.document('audit/{auditId}').onCreate(async(snapshot,context)=>{constauditData=snapshot.data();// Check for multiple failed loginsif(auditData.eventType==='login_failed'){constoneHourAgo=newDate(Date.now()-60*60*1000);constfailedLogins=awaitadmin.firestore().collection('audit').where('eventType','==','login_failed').where('timestamp','>',oneHourAgo).where('userId','==',auditData.userId).get();if(failedLogins.size>5){// Suspend account or send alertawaitadmin.firestore().collection('security_alerts').add({type: 'suspicious_login_attempts',userId: auditData.userId,count: failedLogins.size,timestamp: newDate()});}}});// Security: Clean up old audit logsexports.cleanupOldLogs=functions.pubsub.schedule('every 24 hours').onRun(async(context)=>{constthirtyDaysAgo=newDate(Date.now()-30*24*60*60*1000);constoldLogs=awaitadmin.firestore().collection('audit').where('timestamp','<',thirtyDaysAgo).get();constbatch=admin.firestore().batch();oldLogs.docs.forEach(doc=>{batch.delete(doc.ref);});awaitbatch.commit();console.log(`Cleaned up ${oldLogs.size} old audit logs`);});

7. Environment Security Configuration

.env file

# Firebase ConfigurationREACT_APP_FIREBASE_API_KEY=your_api_key_hereREACT_APP_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.comREACT_APP_FIREBASE_PROJECT_ID=your-project-idREACT_APP_FIREBASE_STORAGE_BUCKET=your-project.appspot.comREACT_APP_FIREBASE_MESSAGING_SENDER_ID=your_sender_idREACT_APP_FIREBASE_APP_ID=your_app_id# SecurityREACT_APP_RECAPTCHA_SITE_KEY=your_recaptcha_site_keyREACT_APP_SECURITY_LOG_RETENTION_DAYS=30

8. Security Best Practices Implementation

// security-best-practices.jsexportclassSecurityBestPractices{staticasyncvalidateFileUpload(file){// Check file size (max 5MB)constmaxSize=5*1024*1024;if(file.size>maxSize){thrownewError('File size too large. Maximum 5MB allowed.');}// Check file typeconstallowedTypes=['image/jpeg','image/png','image/gif','application/pdf'];if(!allowedTypes.includes(file.type)){thrownewError('File type not allowed.');}// Check for potential malicious filesif(file.name.includes('..')||file.name.includes('/')){thrownewError('Invalid file name.');}}staticsanitizeUserInput(input){// Basic XSS preventionreturninput.replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#x27;').replace(/\//g,'&#x2F;');}staticvalidateEmail(email){constemailRegex=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;returnemailRegex.test(email);}staticgenerateSecureToken(length=32){constarray=newUint8Array(length);crypto.getRandomValues(array);returnArray.from(array,byte=>byte.toString(16).padStart(2,'0')).join('');}}

9. Usage Example

// app.jsimportFirebaseAuthSecurityfrom'./firebase-auth-security';import{SecurityBestPractices}from'./security-best-practices';constauthSecurity=newFirebaseAuthSecurity();// Secure user registrationasyncfunctionregisterUser(email,password,displayName){try{awaitSecurityBestPractices.validateEmail(email);constuserCredential=awaitauthSecurity.secureSignUp(email,password,displayName);console.log('User registered securely:',userCredential.user.uid);}catch(error){console.error('Registration failed:',error.message);}}// Secure file uploadasyncfunctionuploadFile(file,userId){try{awaitSecurityBestPractices.validateFileUpload(file);// Proceed with Firebase Storage upload}catch(error){console.error('File upload rejected:',error.message);}}

This comprehensive Firebase security implementation provides:

  • Firestore Security Rules with role-based access
  • Storage Security Rules with user isolation
  • Authentication Security with email verification and session management
  • App Check for API protection
  • Security Monitoring with audit trails
  • Input Validation and sanitization
  • File Upload Security with type and size validation
  • Security Headers for web hosting

The implementation follows Firebase security best practices and provides multiple layers of protection for your application.


CodeAnt-AI Description

Add Firebase security overview and implementation checklist

What Changed

  • Added a developer-facing Firebase security guide at .devcontainer/Securely Fairbase that summarizes the three protection layers: App Check, Authentication, and Security Rules.
  • Included concrete, user-focused examples for Firestore and Realtime Database rules that show how to restrict access so users only read/write their own data.
  • Described role-based access control and data validation patterns that enforce field types and structure before writes are allowed.
  • Provided a clear, step-by-step implementation pathway: enable Authentication, design data structure, write rules, test with the Firebase Local Emulator Suite or console simulator, and deploy rules to production.

Impact

✅ Clearer Firebase security steps for developers
✅ Fewer accidental data exposures during development
✅ Safer production deployments by encouraging emulator testing

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

I'll provide you with comprehensive Firebase security implementation guidance. Here's a detailed security setup:
## 1. Firebase Security Rules & Configuration
### Firebase Security Rules (`firebase.json`)
```json
{
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"storage": {
"rules": "storage.rules"
},
"hosting": {
"public": "public",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"headers": [
{
"source": "**",
"headers": [
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-XSS-Protection",
"value": "1; mode=block"
},
{
"key": "Strict-Transport-Security",
"value": "max-age=31536000; includeSubDomains"
}
]
}
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"emulators": {
"auth": {
"port": 9099
},
"firestore": {
"port": 8080
},
"storage": {
"port": 9199
},
"ui": {
"enabled": true
}
}
}
```
## 2. Firestore Security Rules
### `firestore.rules`
```javascript
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Global read/write control - adjust as needed
match /{document=**} {
allow read, write: if request.auth != null;
}
// Users can only access their own user data
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
allow create: if request.auth != null && request.auth.uid == userId &&
request.resource.data.keys().hasAll(['email', 'createdAt']) &&
request.resource.data.email is string &&
request.resource.data.createdAt is timestamp;
}
// Posts collection - users can read all, but only write their own
match /posts/{postId} {
allow read: if request.auth != null;
allow create: if request.auth != null &&
request.auth.uid == request.resource.data.authorId &&
request.resource.data.keys().hasAll(['title', 'content', 'createdAt']) &&
request.resource.data.title is string &&
request.resource.data.content is string &&
request.resource.data.createdAt is timestamp;
allow update, delete: if request.auth != null && request.auth.uid == resource.data.authorId;
}
// Comments - users can read all, but only write their own
match /posts/{postId}/comments/{commentId} {
allow read: if request.auth != null;
allow create: if request.auth != null &&
request.auth.uid == request.resource.data.authorId &&
request.resource.data.keys().hasAll(['content', 'createdAt']) &&
request.resource.data.content is string &&
request.resource.data.createdAt is timestamp;
allow update, delete: if request.auth != null && request.auth.uid == resource.data.authorId;
}
// Admin role check function
function isAdmin() {
return request.auth.token.admin == true;
}
// Admin-only collections
match /admin/{document=**} {
allow read, write: if isAdmin();
}
// Audit trail - read only for admins
match /audit/{document=**} {
allow read: if isAdmin();
allow write: if request.auth != null;
}
}
}
```
## 3. Firebase Storage Security Rules
### `storage.rules`
```javascript
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
// Users can only upload to their own folder
match /users/{userId}/{allPaths=**} {
allow read: if request.auth != null;
allow write: if request.auth != null && request.auth.uid == userId;
}
// Profile pictures - users can read all, but only write their own
match /profile_pictures/{userId} {
allow read: if request.auth != null;
allow write: if request.auth != null && request.auth.uid == userId;
}
// Post images - readable by all authenticated users
match /post_images/{postId}/{imageId} {
allow read: if request.auth != null;
allow write: if request.auth != null && exists(/databases/$(database)/documents/posts/$(postId)) &&
get(/databases/$(database)/documents/posts/$(postId)).data.authorId == request.auth.uid;
}
// Public read-only files
match /public/{allPaths=**} {
allow read: if true;
allow write: if request.auth != null && isAdmin();
}
function isAdmin() {
return request.auth.token.admin == true;
}
}
}
```
## 4. Firebase Authentication Security
### Security Configuration
```javascript
// firebase-auth-security.js
import { initializeApp } from 'firebase/app';
import { getAuth, createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
updateProfile,
sendEmailVerification,
sendPasswordResetEmail,
setPersistence,
browserSessionPersistence,
browserLocalPersistence,
onAuthStateChanged
} from 'firebase/auth';
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_FIREBASE_APP_ID
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
class FirebaseAuthSecurity {
constructor() {
this.auth = auth;
this.setupSecurityPolicies();
}
setupSecurityPolicies() {
// Set session persistence based on user preference
setPersistence(this.auth, browserLocalPersistence);
// Monitor auth state for security
onAuthStateChanged(this.auth, (user) => {
if (user) {
this.logSecurityEvent('user_signed_in', user.uid);
this.validateUserSession(user);
} else {
this.logSecurityEvent('user_signed_out');
}
});
}
async validateUserSession(user) {
// Check if email is verified
if (!user.emailVerified) {
await sendEmailVerification(user);
throw new Error('Please verify your email before proceeding');
}
// Check if token is recent (less than 1 hour old)
const tokenTime = user.metadata.lastSignInTime;
const currentTime = new Date();
const timeDiff = (currentTime - new Date(tokenTime)) / (1000 * 60 * 60);
if (timeDiff > 24) {
await this.auth.signOut();
throw new Error('Session expired. Please sign in again.');
}
}
async secureSignUp(email, password, displayName) {
try {
// Validate password strength
this.validatePassword(password);
const userCredential = await createUserWithEmailAndPassword(
this.auth, email, password
);
// Update profile
await updateProfile(userCredential.user, {
displayName: displayName
});
// Send email verification
await sendEmailVerification(userCredential.user);
// Log security event
this.logSecurityEvent('user_registered', userCredential.user.uid);
return userCredential;
} catch (error) {
this.logSecurityEvent('registration_failed', null, error.message);
throw error;
}
}
async secureSignIn(email, password) {
try {
const userCredential = await signInWithEmailAndPassword(
this.auth, email, password
);
// Validate session
await this.validateUserSession(userCredential.user);
this.logSecurityEvent('login_success', userCredential.user.uid);
return userCredential;
} catch (error) {
this.logSecurityEvent('login_failed', null, error.message);
throw error;
}
}
validatePassword(password) {
const minLength = 8;
const hasUpperCase = /[A-Z]/.test(password);
const hasLowerCase = /[a-z]/.test(password);
const hasNumbers = /\d/.test(password);
const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(password);
if (password.length < minLength) {
throw new Error('Password must be at least 8 characters long');
}
if (!hasUpperCase) {
throw new Error('Password must contain at least one uppercase letter');
}
if (!hasLowerCase) {
throw new Error('Password must contain at least one lowercase letter');
}
if (!hasNumbers) {
throw new Error('Password must contain at least one number');
}
if (!hasSpecialChar) {
throw new Error('Password must contain at least one special character');
}
}
async logSecurityEvent(eventType, userId = null, details = null) {
// Log to Firestore for audit trail
const securityLog = {
eventType,
userId,
timestamp: new Date(),
userAgent: navigator.userAgent,
ipAddress: await this.getClientIP(),
details
};
// In a real app, you'd write this to Firestore
console.log('Security Event:', securityLog);
}
async getClientIP() {
// This would typically be handled by a cloud function
// that can see the real IP address
return 'client-ip-not-available-in-client';
}
}
export default FirebaseAuthSecurity;
```
## 5. Firebase App Check Implementation
```javascript
// firebase-app-check.js
import { initializeAppCheck, ReCaptchaV3Provider } from 'firebase/app-check';
const appCheck = initializeAppCheck(app, {
provider: new ReCaptchaV3Provider('your-recaptcha-v3-site-key'),
isTokenAutoRefreshEnabled: true
});
```
## 6. Firebase Security Functions
### Cloud Functions for Security
```javascript
// functions/security.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
// Security: Monitor for suspicious activities
exports.monitorSuspiciousActivities = functions.firestore
.document('audit/{auditId}')
.onCreate(async (snapshot, context) => {
const auditData = snapshot.data();
// Check for multiple failed logins
if (auditData.eventType === 'login_failed') {
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);
const failedLogins = await admin.firestore()
.collection('audit')
.where('eventType', '==', 'login_failed')
.where('timestamp', '>', oneHourAgo)
.where('userId', '==', auditData.userId)
.get();
if (failedLogins.size > 5) {
// Suspend account or send alert
await admin.firestore()
.collection('security_alerts')
.add({
type: 'suspicious_login_attempts',
userId: auditData.userId,
count: failedLogins.size,
timestamp: new Date()
});
}
}
});
// Security: Clean up old audit logs
exports.cleanupOldLogs = functions.pubsub
.schedule('every 24 hours')
.onRun(async (context) => {
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
const oldLogs = await admin.firestore()
.collection('audit')
.where('timestamp', '<', thirtyDaysAgo)
.get();
const batch = admin.firestore().batch();
oldLogs.docs.forEach(doc => {
batch.delete(doc.ref);
});
await batch.commit();
console.log(`Cleaned up ${oldLogs.size} old audit logs`);
});
```
## 7. Environment Security Configuration
### `.env` file
```env
# Firebase Configuration
REACT_APP_FIREBASE_API_KEY=your_api_key_here
REACT_APP_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
REACT_APP_FIREBASE_PROJECT_ID=your-project-id
REACT_APP_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
REACT_APP_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
REACT_APP_FIREBASE_APP_ID=your_app_id
# Security
REACT_APP_RECAPTCHA_SITE_KEY=your_recaptcha_site_key
REACT_APP_SECURITY_LOG_RETENTION_DAYS=30
```
## 8. Security Best Practices Implementation
```javascript
// security-best-practices.js
export class SecurityBestPractices {
static async validateFileUpload(file) {
// Check file size (max 5MB)
const maxSize = 5 * 1024 * 1024;
if (file.size > maxSize) {
throw new Error('File size too large. Maximum 5MB allowed.');
}
// Check file type
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf'];
if (!allowedTypes.includes(file.type)) {
throw new Error('File type not allowed.');
}
// Check for potential malicious files
if (file.name.includes('..') || file.name.includes('/')) {
throw new Error('Invalid file name.');
}
}
static sanitizeUserInput(input) {
// Basic XSS prevention
return input
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#x27;')
.replace(/\//g, '&#x2F;');
}
static validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
static generateSecureToken(length = 32) {
const array = new Uint8Array(length);
crypto.getRandomValues(array);
return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
}
}
```
## 9. Usage Example
```javascript
// app.js
import FirebaseAuthSecurity from './firebase-auth-security';
import { SecurityBestPractices } from './security-best-practices';
const authSecurity = new FirebaseAuthSecurity();
// Secure user registration
async function registerUser(email, password, displayName) {
try {
await SecurityBestPractices.validateEmail(email);
const userCredential = await authSecurity.secureSignUp(email, password, displayName);
console.log('User registered securely:', userCredential.user.uid);
} catch (error) {
console.error('Registration failed:', error.message);
}
}
// Secure file upload
async function uploadFile(file, userId) {
try {
await SecurityBestPractices.validateFileUpload(file);
// Proceed with Firebase Storage upload
} catch (error) {
console.error('File upload rejected:', error.message);
}
}
```
This comprehensive Firebase security implementation provides:
- ✅ **Firestore Security Rules** with role-based access
- ✅ **Storage Security Rules** with user isolation
- ✅ **Authentication Security** with email verification and session management
- ✅ **App Check** for API protection
- ✅ **Security Monitoring** with audit trails
- ✅ **Input Validation** and sanitization
- ✅ **File Upload Security** with type and size validation
- ✅ **Security Headers** for web hosting
The implementation follows Firebase security best practices and provides multiple layers of protection for your application.
@codeant-ai

Copy link
Copy Markdown

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@Sazwanismail
Sazwanismail merged commit ba58ec7 into mainOct 17, 2025
1 check passed
@codeant-aicodeant-aiBot added the size:M This PR changes 30-99 lines, ignoring generated files label Oct 17, 2025
@codeant-ai

Copy link
Copy Markdown

CodeAnt AI finished reviewing your PR.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Black settingLaman sendiribugSomething isn't workingsize:MThis PR changes 30-99 lines, ignoring generated filesWindows hunterProjects personal

Projects

Development

Successfully merging this pull request may close these issues.

New Issue: Additional Information Needed [Draft] New Issue in codespaces-react Ms Bot

1 participant

@Sazwanismail