MongoDB Security & Authentication
Protect your database with authentication and authorization
🔐 What is MongoDB Security?
MongoDB security protects your data through authentication, authorization, encryption, and network security. It ensures only authorized users access specific data with appropriate permissions, preventing unauthorized access and data breaches.
// Create user with authentication
db.createUser({
user: "appUser",
pwd: "securePassword123",
roles: [{ role: "readWrite", db: "myapp" }]
})
Result:
User created with read/write access to myapp database
Key Security Features
Authentication
Verify user identity
db.auth("username", "password")
Authorization
Control user permissions
roles: ["readWrite", "dbAdmin"]
Encryption
Encrypt data at rest and in transit
--tlsMode requireTLS
Network Security
Restrict network access
--bind_ip 127.0.0.1
🔹 Enabling Authentication
Enable authentication to require users to identify themselves before accessing the database. Start MongoDB with authentication enabled and create an admin user first.
// 1. Start MongoDB without authentication
mongod --port 27017 --dbpath /data/db
// 2. Connect and create admin user
use admin
db.createUser({
user: "admin",
pwd: "strongAdminPassword",
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" }
]
})
// 3. Restart MongoDB with authentication
mongod --auth --port 27017 --dbpath /data/db
// 4. Connect with authentication
mongosh --port 27017 -u "admin" -p "strongAdminPassword" --authenticationDatabase "admin"
// Or authenticate after connecting
use admin
db.auth("admin", "strongAdminPassword")
// In application code (Node.js)
const { MongoClient } = require('mongodb');
const uri = "mongodb://admin:strongAdminPassword@localhost:27017/?authSource=admin";
const client = new MongoClient(uri);
Result:
Authentication enabled. Users must provide credentials to access database.
🔹 Creating Users and Roles
Create users with specific roles to control database access. Assign built-in roles or create custom roles with precise permissions for different application needs.
// Create application user with read/write access
use myapp
db.createUser({
user: "appUser",
pwd: "appPassword123",
roles: [
{ role: "readWrite", db: "myapp" }
]
})
// Create read-only user
db.createUser({
user: "analyst",
pwd: "analystPass",
roles: [
{ role: "read", db: "myapp" }
]
})
// Create user with multiple roles
db.createUser({
user: "developer",
pwd: "devPassword",
roles: [
{ role: "readWrite", db: "myapp" },
{ role: "dbAdmin", db: "myapp" }
]
})
// Built-in roles:
// - read: Read data from all non-system collections
// - readWrite: Read and write data
// - dbAdmin: Database administration tasks
// - userAdmin: Create and modify users and roles
// - clusterAdmin: Cluster administration
// - root: Full access to all resources
// View user information
db.getUser("appUser")
// Update user password
db.changeUserPassword("appUser", "newPassword456")
// Grant additional role
db.grantRolesToUser("appUser", [{ role: "dbAdmin", db: "myapp" }])
// Revoke role
db.revokeRolesFromUser("appUser", [{ role: "dbAdmin", db: "myapp" }])
// Delete user
db.dropUser("appUser")
Result:
Users created with appropriate permissions for their roles
🔹 Custom Roles
Create custom roles with specific privileges for fine-grained access control. Define exactly which actions users can perform on which resources for enhanced security.
// Create custom role with specific privileges
use myapp
db.createRole({
role: "ordersManager",
privileges: [
{
resource: { db: "myapp", collection: "orders" },
actions: ["find", "insert", "update"]
},
{
resource: { db: "myapp", collection: "customers" },
actions: ["find"] // Read-only on customers
}
],
roles: [] // No inherited roles
})
// Create role with inherited roles
db.createRole({
role: "seniorDeveloper",
privileges: [
{
resource: { db: "myapp", collection: "" }, // All collections
actions: ["find", "insert", "update", "remove"]
}
],
roles: [
{ role: "read", db: "logs" } // Also read logs database
]
})
// Assign custom role to user
db.createUser({
user: "orderManager",
pwd: "managerPass",
roles: ["ordersManager"]
})
// Common actions:
// - find, insert, update, remove
// - createCollection, dropCollection
// - createIndex, dropIndex
// - viewRole, viewUser
// View role details
db.getRole("ordersManager", { showPrivileges: true })
// Update role
db.updateRole("ordersManager", {
privileges: [
{
resource: { db: "myapp", collection: "orders" },
actions: ["find", "insert", "update", "remove"] // Added remove
}
]
})
Result:
Custom role created with precise permissions
🔹 Connection String Security
Secure your connection strings by using environment variables, avoiding hardcoded credentials, and implementing proper authentication mechanisms in your application code.
// ❌ BAD: Hardcoded credentials
const uri = "mongodb://admin:password123@localhost:27017/myapp";
// ✅ GOOD: Use environment variables
const uri = `mongodb://${process.env.DB_USER}:${process.env.DB_PASS}@${process.env.DB_HOST}:27017/myapp`;
// Connection string format
// mongodb://[username:password@]host[:port][/database][?options]
// With authentication database
const uri = "mongodb://appUser:appPass@localhost:27017/myapp?authSource=admin";
// MongoDB Atlas connection (cloud)
const uri = "mongodb+srv://username:[email protected]/myapp?retryWrites=true&w=majority";
// With TLS/SSL
const uri = "mongodb://user:pass@host:27017/db?tls=true&tlsCAFile=/path/to/ca.pem";
// Connection options for security
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
tls: true,
tlsAllowInvalidCertificates: false, // Validate certificates
authSource: 'admin',
authMechanism: 'SCRAM-SHA-256'
});
// .env file example
// DB_USER=appUser
// DB_PASS=securePassword123
// DB_HOST=localhost
// DB_NAME=myapp
// Load environment variables
require('dotenv').config();
const uri = `mongodb://${process.env.DB_USER}:${process.env.DB_PASS}@${process.env.DB_HOST}:27017/${process.env.DB_NAME}`;
Best Practice:
Always use environment variables, never commit credentials to version control
🔹 Network Security
Restrict network access to your MongoDB instance using IP whitelisting, firewalls, and binding to specific network interfaces. Limit exposure to trusted networks only.
// Bind to specific IP (localhost only)
mongod --bind_ip 127.0.0.1
// Bind to multiple IPs
mongod --bind_ip 127.0.0.1,192.168.1.100
// Configuration file (mongod.conf)
net:
port: 27017
bindIp: 127.0.0.1,192.168.1.100
security:
authorization: enabled
// Enable TLS/SSL
net:
tls:
mode: requireTLS
certificateKeyFile: /path/to/mongodb.pem
CAFile: /path/to/ca.pem
// Firewall rules (Linux iptables)
// Allow only specific IP
sudo iptables -A INPUT -p tcp -s 192.168.1.100 --dport 27017 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 27017 -j DROP
// MongoDB Atlas (cloud) - IP Whitelist
// Add your application server IPs in Atlas dashboard
// Network Access → IP Access List → Add IP Address
// VPC Peering for private connections
// Connect Atlas to your cloud provider's VPC
// Use VPN for remote access
// Don't expose MongoDB directly to the internet
Security Checklist:
✅ Bind to specific IPs ✅ Enable firewall ✅ Use TLS ✅ Whitelist IPs
🔹 Encryption
Protect data with encryption at rest and in transit. Use TLS for network encryption and enable encryption at rest for sensitive data stored on disk.
// Encryption in Transit (TLS/SSL)
// Start MongoDB with TLS
mongod --tlsMode requireTLS \
--tlsCertificateKeyFile /path/to/mongodb.pem \
--tlsCAFile /path/to/ca.pem
// Connect with TLS
mongosh --tls \
--tlsCertificateKeyFile /path/to/client.pem \
--tlsCAFile /path/to/ca.pem \
--host mongodb.example.com
// In application (Node.js)
const client = new MongoClient(uri, {
tls: true,
tlsCertificateKeyFile: '/path/to/client.pem',
tlsCAFile: '/path/to/ca.pem'
});
// Encryption at Rest (Enterprise feature)
// mongod.conf
security:
enableEncryption: true
encryptionKeyFile: /path/to/keyfile
// Client-Side Field Level Encryption (CSFLE)
const { ClientEncryption } = require('mongodb-client-encryption');
const encryption = new ClientEncryption(client, {
keyVaultNamespace: 'encryption.__keyVault',
kmsProviders: {
local: {
key: Buffer.from(process.env.MASTER_KEY, 'base64')
}
}
});
// Encrypt sensitive field
const encryptedSSN = await encryption.encrypt(
'123-45-6789',
{
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic',
keyId: dataKeyId
}
);
// Store encrypted data
await db.users.insertOne({
name: "John Doe",
ssn: encryptedSSN // Encrypted field
});
Encryption Types:
In Transit (TLS) | At Rest (Enterprise) | Field-Level (CSFLE)
🔹 Security Best Practices
Follow these essential security guidelines to protect your MongoDB deployment. Implement defense in depth with multiple security layers for comprehensive protection.
✅ Essential Security Measures:
- Enable authentication: Always require user credentials
- Use strong passwords: Minimum 12 characters, mixed case, numbers, symbols
- Principle of least privilege: Grant minimum required permissions
- Enable TLS/SSL: Encrypt data in transit
- Restrict network access: Use firewalls and IP whitelisting
- Regular updates: Keep MongoDB version current
- Audit logging: Track database access and changes
- Backup encryption: Encrypt backup files
❌ Security Mistakes to Avoid:
- Running without authentication enabled
- Using default ports without firewall
- Exposing MongoDB directly to internet
- Hardcoding credentials in code
- Granting excessive permissions
- Ignoring security updates
- Not encrypting sensitive data
// Security configuration checklist
// mongod.conf
security:
authorization: enabled
net:
bindIp: 127.0.0.1,192.168.1.100
tls:
mode: requireTLS
certificateKeyFile: /path/to/cert.pem
systemLog:
destination: file
path: /var/log/mongodb/mongod.log
auditLog:
destination: file
path: /var/log/mongodb/audit.log