MongoDB Security Guide: Atlas Configuration and Best Practices

Share

TL;DR

MongoDB Atlas requires proper network access configuration and authentication. Never allow access from 0.0.0.0/0 in production. Create database users with minimal permissions, store connection strings in environment variables, and use VPC peering or private endpoints for production workloads. Atlas encrypts data at rest and in transit by default.

MongoDB Atlas Security Model

MongoDB Atlas is a managed database service. Security is handled at multiple levels:

  • Network access: IP allowlist controls who can connect
  • Authentication: Database users with usernames/passwords
  • Authorization: Roles define what users can do
  • Encryption: Data encrypted at rest and in transit

Network Access Configuration

The most common security mistake is overly permissive network access.

The Danger of 0.0.0.0/0

Never use 0.0.0.0/0 in production. This allows connections from any IP address. If your credentials are leaked, anyone can access your database.

Proper Network Configuration

EnvironmentRecommended Approach
DevelopmentAdd your current IP address
Vercel/NetlifyUse their IP ranges or 0.0.0.0/0 with strong auth
Railway/RenderUse their static IPs or private networking
AWS/GCP/AzureVPC Peering or Private Endpoints

Serverless platforms: Services like Vercel use dynamic IPs. You may need to allow broad access but should combine this with strong authentication and minimal user permissions.

Database User Security

Creating Secure Users

Create database users with minimal necessary permissions:

User role examples
# Read-only user for reporting
Username: reporter
Role: read (on specific database)

# Application user with read/write
Username: app_user
Role: readWrite (on specific database)

# Admin user (use sparingly)
Username: admin
Role: atlasAdmin

User Best Practices

  • Use separate users for different applications
  • Use separate users for different environments (dev, staging, prod)
  • Generate strong, unique passwords
  • Rotate passwords periodically
  • Never share database credentials

Connection String Security

MongoDB connection string format
mongodb+srv://username:password@cluster.xxxxx.mongodb.net/database?retryWrites=true&w=majority

Never hardcode connection strings. They contain your username and password. Always use environment variables.

Secure connection in Node.js
const { MongoClient } = require('mongodb');

// Get connection string from environment
const uri = process.env.MONGODB_URI;

if (!uri) {
  throw new Error('MONGODB_URI environment variable is required');
}

const client = new MongoClient(uri, {
  // These options are now defaults in newer drivers
  // but good to be explicit
  retryWrites: true,
  w: 'majority'
});

async function connect() {
  try {
    await client.connect();
    console.log('Connected to MongoDB');
  } catch (error) {
    console.error('MongoDB connection error:', error.message);
    process.exit(1);
  }
}

Query Security

Preventing NoSQL Injection

MongoDB queries can be vulnerable to injection if you pass user input directly:

Vulnerable to injection
// DANGEROUS: User could send { "$gt": "" } as password
app.post('/login', async (req, res) => {
  const user = await db.collection('users').findOne({
    email: req.body.email,
    password: req.body.password  // Could be an object!
  });
});
Safe approach
// SAFE: Validate and sanitize input
app.post('/login', async (req, res) => {
  const { email, password } = req.body;

  // Ensure inputs are strings
  if (typeof email !== 'string' || typeof password !== 'string') {
    return res.status(400).json({ error: 'Invalid input' });
  }

  // Hash comparison (never store plain passwords!)
  const user = await db.collection('users').findOne({ email });
  if (!user || !await bcrypt.compare(password, user.passwordHash)) {
    return res.status(401).json({ error: 'Invalid credentials' });
  }
});

Input Validation Library

Using a validation library
const Joi = require('joi');

const userSchema = Joi.object({
  email: Joi.string().email().required(),
  password: Joi.string().min(8).required()
});

app.post('/login', async (req, res) => {
  // Validate input
  const { error, value } = userSchema.validate(req.body);
  if (error) {
    return res.status(400).json({ error: error.details[0].message });
  }

  // Now value.email and value.password are guaranteed to be strings
  const { email, password } = value;
  // ... proceed safely
});

Encryption

Encryption at Rest

Atlas encrypts all data at rest using AES-256. This is enabled by default and cannot be disabled.

Encryption in Transit

All connections to Atlas use TLS. The connection string with mongodb+srv:// enforces TLS.

Client-Side Field Level Encryption

For highly sensitive data, Atlas supports client-side encryption where data is encrypted before sending to the database:

Field level encryption concept
// With CSFLE, sensitive fields are encrypted client-side
// The database never sees the plaintext

// Fields like SSN, credit card would be encrypted
{
  name: "John Doe",                    // Plaintext
  ssn: Binary(encrypted_data),         // Encrypted
  creditCard: Binary(encrypted_data)   // Encrypted
}

MongoDB Atlas Security Checklist

Before Going to Production

Network access restricted (not 0.0.0.0/0 if possible)

Database users have minimal necessary roles

Separate users for each application/environment

Strong, unique passwords for all users

Connection string in environment variables

Input validation prevents NoSQL injection

Audit logging enabled (for compliance needs)

Backups configured and tested

Is it safe to allow 0.0.0.0/0 network access?

It's not ideal but sometimes necessary for serverless platforms. If you must allow all IPs, use strong authentication, create users with minimal permissions, and consider Atlas's network peering for sensitive data.

How do I connect from Vercel or Netlify?

These platforms use dynamic IPs. You'll typically need to allow broad network access (0.0.0.0/0) but should compensate with strong passwords, minimal user permissions, and input validation in your code.

Should I use the same database user for all environments?

No. Create separate users for development, staging, and production. This limits damage if credentials are compromised and makes it easier to rotate credentials.

What happens if my connection string is exposed?

Immediately rotate the database user's password in Atlas. Then update your environment variables with the new connection string. Also audit your database for any unauthorized access or changes.

Using MongoDB?

Scan your project for exposed connection strings and security issues.

Start Free Scan
Tool & Platform Guides

MongoDB Security Guide: Atlas Configuration and Best Practices