MongoDB Security: Authentication, RBAC, and TLS Configuration
Secure MongoDB with authentication, role-based access control (RBAC), network hardening, TLS/SSL, and field-level encryption. Lesson 8 of the MongoDB & NoSQL Mastery course.

An unsecured MongoDB instance is one of the most common causes of data breaches in the NoSQL ecosystem. Thousands of databases have been exposed publicly with no authentication. This lesson covers the full security stack: enabling authentication, creating scoped users, configuring TLS, and hardening the network — transforming a default-open development instance into a production-ready deployment.
Previous: Lesson 7 — Indexes: Performance & Design
Enabling Authentication
MongoDB ships with authentication disabled by default for development convenience. Never expose this configuration beyond localhost.
Step 1: Create the First Admin User
Before enabling authentication, create the admin user while the database is still open:
// In mongosh (no auth required yet)
use admin
db.createUser({
user: "admin",
pwd: passwordPrompt(), // prompts securely — never hardcode passwords
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" },
{ role: "dbAdminAnyDatabase", db: "admin" },
{ role: "clusterAdmin", db: "admin" }
]
})Step 2: Enable Authentication in mongod.conf
# /etc/mongod.conf
security:
authorization: enabledsudo systemctl restart mongodStep 3: Connect with Credentials
mongosh -u admin -p --authenticationDatabase adminRole-Based Access Control (RBAC)
MongoDB's RBAC model: users are assigned roles; roles grant privileges (actions on resources).
Built-In Roles
| Role | Access Level |
|---|---|
read | Read documents and indexes in a specific database |
readWrite | Read and write documents in a specific database |
dbAdmin | Schema management, index management, stats — no data access |
userAdmin | Create and modify users and roles in a specific database |
clusterAdmin | Sharding, replication management — admin database only |
readAnyDatabase | Read across all databases |
root | Superuser — unrestricted access to everything |
Creating Application Users
Follow the principle of least privilege: application users should only have access to their own database, with only the operations they need:
use myapp
// Read-only service account (e.g. for a reporting tool)
db.createUser({
user: "reporting_service",
pwd: passwordPrompt(),
roles: [{ role: "read", db: "myapp" }]
})
// Application service account — read/write own database only
db.createUser({
user: "app_service",
pwd: passwordPrompt(),
roles: [{ role: "readWrite", db: "myapp" }]
})
// Migration user — needs dbAdmin for index creation
db.createUser({
user: "migration_runner",
pwd: passwordPrompt(),
roles: [
{ role: "readWrite", db: "myapp" },
{ role: "dbAdmin", db: "myapp" }
]
})Custom Roles
use myapp
db.createRole({
role: "orderProcessor",
privileges: [
{
resource: { db: "myapp", collection: "orders" },
actions: ["find", "update"]
},
{
resource: { db: "myapp", collection: "products" },
actions: ["find"]
}
],
roles: []
})
db.createUser({
user: "order_worker",
pwd: passwordPrompt(),
roles: [{ role: "orderProcessor", db: "myapp" }]
})Managing Users
// List all users in the current database
db.getUsers()
// Update a user's password
db.changeUserPassword("app_service", passwordPrompt())
// Add a role to an existing user
db.grantRolesToUser("app_service", [{ role: "dbAdmin", db: "myapp" }])
// Remove a role
db.revokeRolesFromUser("app_service", [{ role: "dbAdmin", db: "myapp" }])
// Delete a user
db.dropUser("migration_runner")Network Hardening
Bind to Specific Interfaces
By default, MongoDB 3.6+ binds only to 127.0.0.1. For a server accessible to application instances, bind to the specific private IP — never 0.0.0.0 in production:
# /etc/mongod.conf
net:
bindIp: 127.0.0.1,10.0.1.15 # localhost + private network IP only
port: 27017Firewall Rules
# Allow MongoDB access only from the application server (UFW example)
sudo ufw allow from 10.0.1.20 to any port 27017
# Deny all other access to port 27017
sudo ufw deny 27017Change the Default Port
net:
port: 27937 # Non-standard port — minor security-through-obscurity measureTLS/SSL Configuration
TLS encrypts data in transit between MongoDB clients and the server.
Generate Certificates (Self-Signed for Testing)
# Generate CA key and certificate
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 1826 -key ca.key -out ca.crt \
-subj "/CN=MongoDB CA"
# Generate server key and certificate signed by the CA
openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr \
-subj "/CN=mongodb.internal"
openssl x509 -req -days 730 -in server.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
# Combine key and certificate into a PEM file (required by MongoDB)
cat server.key server.crt > server.pemEnable TLS in mongod.conf
# /etc/mongod.conf
net:
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/tls/server.pem
CAFile: /etc/mongodb/tls/ca.crtConnect with TLS
mongosh --tls \
--tlsCertificateKeyFile /etc/mongodb/tls/client.pem \
--tlsCAFile /etc/mongodb/tls/ca.crt \
"mongodb://admin@mongodb.internal:27017/admin"Auditing and Monitoring Security Events
// View active connections
db.currentOp(true)
// Check authentication mechanisms configured
db.adminCommand({ getParameter: 1, authenticationMechanisms: 1 })
// List all roles in the admin database
use admin
db.getRoles({ showBuiltinRoles: true })
// Check which roles a user has
db.getUser("app_service")MongoDB Atlas Security (Managed)
On Atlas, security is configured via the UI or API:
- Network access: IP allowlist or VPC peering — no public IP exposure
- Database users: Scoped to specific databases with built-in or custom roles
- TLS: Always enabled; certificates managed by Atlas
- Encryption at rest: AES-256 by default on all clusters
- Audit logging: Available on M10+ clusters — logs all operations to a queryable log
