The "bad auth : authentication failed" error in MongoDB occurs when the database server rejects client authentication credentials. This typically happens due to incorrect username/password, missing authentication database, or misconfigured user permissions. The error indicates that MongoDB cannot verify the identity of the connecting client against its authentication system.
The "MongoServerError: bad auth : authentication failed" error is MongoDB's way of telling your application that the authentication credentials provided during connection establishment are invalid or insufficient. MongoDB uses a role-based access control (RBAC) system where users must be explicitly created with specific privileges to access databases. When a MongoDB client (application, driver, or tool) attempts to connect to a MongoDB instance with authentication enabled, it must provide: 1. A valid username 2. The correct password for that username 3. The correct authentication database (where the user is defined) 4. Proper connection string format with authentication parameters Common scenarios where this error appears: - **Incorrect credentials**: Username or password doesn't match what's stored in MongoDB - **Wrong authentication database**: User exists in a different database than specified - **Missing authentication parameters**: Connection string doesn't include authSource or authMechanism - **User doesn't exist**: The specified username hasn't been created in MongoDB - **Network-level authentication issues**: SSL/TLS certificate problems or network configuration - **Driver-specific authentication issues**: Different MongoDB drivers may handle authentication differently The error is particularly common when: - Migrating from development to production environments - Setting up new MongoDB instances with authentication - Rotating database credentials - Connecting from different applications or services - Using MongoDB Atlas with incorrect connection strings
First, double-check your connection string for accuracy. The most common issue is simple typos in username, password, or database name.
Standard connection string format:
// Correct format with authentication
mongodb://username:password@host:port/database?authSource=admin
// MongoDB Atlas format
mongodb+srv://username:[email protected]/database?retryWrites=true&w=majorityCheck each component:
1. Username: Case-sensitive, must match exactly what's in MongoDB
2. Password: Special characters need URL encoding (use encodeURIComponent())
3. Host: Correct server address (localhost, IP, or Atlas cluster URL)
4. Port: Default is 27017
5. Database: The database you want to use (not necessarily auth database)
6. authSource: The database where user credentials are stored (usually "admin")
Test with mongosh/mongo shell:
# Connect with explicit authentication
mongosh "mongodb://username:password@localhost:27017/mydb?authSource=admin"
# Or connect and authenticate separately
mongosh --host localhost --port 27017
use admin
db.auth("username", "password")URL encode special characters in password:
// If password is "pass@word#123"
const encodedPassword = encodeURIComponent("pass@word#123");
const connectionString = `mongodb://username:${encodedPassword}@localhost:27017/mydb?authSource=admin`;Verify that the user actually exists and has proper permissions. Connect to MongoDB with administrative privileges (or without authentication if disabled) to check.
Connect without authentication (if possible):
mongosh --host localhost --port 27017Check users in the authentication database (usually "admin"):
// Switch to admin database
use admin
// List all users
db.getUsers()
// Check specific user
db.getUser("username")
// Check user roles and privileges
db.getUser("username").rolesIf user doesn't exist, create it:
use admin
// Create user with read/write access to specific database
db.createUser({
user: "username",
pwd: "password",
roles: [
{ role: "readWrite", db: "mydb" },
{ role: "read", db: "reporting" }
]
})
// Or create user with admin privileges
db.createUser({
user: "adminUser",
pwd: "adminPassword",
roles: ["root"]
})Update existing user password:
use admin
db.changeUserPassword("username", "newPassword")Verify user can access target database:
// Authenticate as the user
db.auth("username", "password")
// Try to access the database
use mydb
db.test.insertOne({ test: 1 }) // Should succeed if permissions are correctThe authSource parameter specifies which database contains the user credentials. This is often different from the database you want to use.
Common scenarios:
- Users created in "admin" database: ?authSource=admin
- Users created in target database: ?authSource=mydb
- MongoDB Atlas: Usually ?authSource=admin
Check where user is actually stored:
// Connect with admin privileges
use admin
// Check all databases for users
const dbs = db.adminCommand({ listDatabases: 1 }).databases;
dbs.forEach(dbInfo => {
const dbName = dbInfo.name;
const userCount = db.getSiblingDB(dbName).getUsers().length;
if (userCount > 0) {
print("Database " + dbName + " has " + userCount + " user(s)");
db.getSiblingDB(dbName).getUsers().forEach(user => {
print(" User: " + user.user);
});
}
});Connection string examples with correct authSource:
// User in admin database, connecting to mydb
const uri1 = 'mongodb://username:password@localhost:27017/mydb?authSource=admin';
// User in mydb database, connecting to mydb
const uri2 = 'mongodb://username:password@localhost:27017/mydb?authSource=mydb';
// MongoDB Atlas with authSource
const uri3 = 'mongodb+srv://username:[email protected]/mydb?authSource=admin&retryWrites=true&w=majority';
// Multiple parameters
const uri4 = 'mongodb://username:password@localhost:27017/mydb?authSource=admin&authMechanism=SCRAM-SHA-256';In application code:
// Node.js MongoDB driver
const { MongoClient } = require('mongodb');
const uri = 'mongodb://username:password@localhost:27017/mydb?authSource=admin';
const client = new MongoClient(uri);
// Mongoose
const mongoose = require('mongoose');
mongoose.connect('mongodb://username:password@localhost:27017/mydb', {
authSource: 'admin',
authMechanism: 'SCRAM-SHA-256',
});MongoDB supports different authentication mechanisms. The default changed from SCRAM-SHA-1 to SCRAM-SHA-256 in MongoDB 4.0.
Check MongoDB version:
mongosh --eval "db.version()"Check supported authentication mechanisms:
// In mongosh
db.adminCommand({ getParameter: 1, authenticationMechanisms: 1 })Common authentication mechanisms:
- SCRAM-SHA-1: Default for MongoDB 3.0+
- SCRAM-SHA-256: Default for MongoDB 4.0+, more secure
- MONGODB-X509: For SSL/TLS certificate authentication
- GSSAPI: For Kerberos authentication
- PLAIN: For LDAP authentication
Specify authentication mechanism in connection string:
// Explicitly specify SCRAM-SHA-256
const uri = 'mongodb://username:password@localhost:27017/mydb?authSource=admin&authMechanism=SCRAM-SHA-256';
// For MongoDB Atlas (usually SCRAM-SHA-256)
const atlasUri = 'mongodb+srv://username:[email protected]/mydb?authMechanism=SCRAM-SHA-256&retryWrites=true&w=majority';If using older MongoDB (< 4.0) or older drivers:
// Force SCRAM-SHA-1 for compatibility
const uri = 'mongodb://username:password@localhost:27017/mydb?authSource=admin&authMechanism=SCRAM-SHA-1';Update MongoDB driver if needed:
# Node.js MongoDB driver
npm install mongodb@latest
# Mongoose
npm install mongoose@latestCheck driver compatibility:
const { MongoClient } = require('mongodb');
console.log('Driver version:', require('mongodb/package.json').version);Network-level issues can prevent authentication. Check firewalls, SSL/TLS, and MongoDB configuration.
Check MongoDB authentication is actually enabled:
# Check mongod configuration
cat /etc/mongod.conf | grep -A5 -B5 security
# Or in mongosh
db.adminCommand({ getParameter: 1, auth: 1 })Typical mongod.conf security section:
security:
authorization: enabled # This enables authentication
# Other security settings...Check firewall rules allow MongoDB port (default 27017):
# Linux iptables
sudo iptables -L -n | grep 27017
# Linux firewalld
sudo firewall-cmd --list-all | grep 27017
# Windows
netsh advfirewall firewall show rule name=all | findstr 27017For MongoDB Atlas, check Network Access:
1. Log into Atlas dashboard
2. Go to your cluster → Security → Network Access
3. Ensure your IP address is whitelisted (or use 0.0.0.0/0 for testing)
4. Check Database Access for user permissions
Test network connectivity:
# Test basic connectivity
ping mongodb-host
# Test MongoDB port
nc -zv mongodb-host 27017
# Test with authentication (using mongosh)
mongosh "mongodb://username:password@mongodb-host:27017/admin?authSource=admin" --eval "db.runCommand({ping:1})"If using SSL/TLS:
// Connection string with SSL
const uri = 'mongodb://username:password@localhost:27017/mydb?authSource=admin&ssl=true';
// With specific SSL options (Node.js driver)
const client = new MongoClient(uri, {
ssl: true,
sslValidate: true,
sslCA: fs.readFileSync('/path/to/ca.pem'),
sslCert: fs.readFileSync('/path/to/client.pem'),
sslKey: fs.readFileSync('/path/to/client.key'),
});MongoDB logs contain detailed authentication failure information. Enable verbose logging to see what's happening.
Check MongoDB logs:
# Typical log locations
tail -f /var/log/mongodb/mongod.log
tail -f /var/log/mongodb/mongodb.log
# Docker containers
docker logs mongodb-containerLook for authentication-related messages:
- "Authentication failed"
- "User not found"
- "SCRAM-SHA-1/256 authentication failed"
- "Client connection dropped during authentication"
Enable verbose authentication logging:
// In mongosh, set log level
db.adminCommand({
setParameter: 1,
logLevel: 2 // 0=off, 1=error, 2=warning, 3=info, 4=debug, 5=trace
})
// Or set component-specific logging
db.adminCommand({
setParameter: 1,
logComponentVerbosity: {
authentication: { verbosity: 2 }
}
})Use diagnostic commands:
// Check current connections and their authentication state
db.currentOp(true).inprog.forEach(op => {
if (op.clientMetadata) {
print("Connection from " + op.client + ", authenticated: " + (op.clientMetadata.auth || "none"));
}
});
// Check authentication statistics
db.serverStatus().connections
db.serverStatus().security
// Check user authentication attempts (if audit logging enabled)
use admin
db.system.audit.find({ "atype": "authenticate" }).sort({ ts: -1 }).limit(10)Test with different connection methods:
# Test with mongosh
mongosh --username username --password password --authenticationDatabase admin --host localhost --port 27017
# Test with mongoimport (if applicable)
mongoimport --uri "mongodb://username:password@localhost:27017/mydb?authSource=admin" --collection test --file data.json
# Test with Compass (MongoDB GUI)
# Download MongoDB Compass and test connection visuallyCreate a minimal test script:
// test-auth.js
const { MongoClient } = require('mongodb');
async function testAuth() {
const uri = 'mongodb://username:password@localhost:27017/mydb?authSource=admin';
try {
const client = new MongoClient(uri);
await client.connect();
console.log('Authentication successful!');
const db = client.db('mydb');
const collections = await db.listCollections().toArray();
console.log('Collections:', collections.map(c => c.name));
await client.close();
} catch (error) {
console.error('Authentication failed:', error.message);
console.error('Full error:', error);
}
}
testAuth();MongoDB Authentication Architecture:
MongoDB uses a pluggable authentication system with these components:
1. Authentication Database: Each user is associated with a specific database (usually "admin"). This database stores user credentials and is specified via authSource parameter.
2. SCRAM (Salted Challenge Response Authentication Mechanism):
- SCRAM-SHA-1: Uses SHA-1 hashing (deprecated but still supported)
- SCRAM-SHA-256: Uses SHA-256 hashing (default since MongoDB 4.0)
- Both use salted passwords to prevent rainbow table attacks
3. Role-Based Access Control (RBAC):
- Built-in roles: read, readWrite, dbAdmin, userAdmin, clusterAdmin, backup, restore, etc.
- Custom roles: Can be created with specific privileges
- Database-specific roles: Roles are defined per database but can grant cross-database privileges
4. Authentication Mechanisms:
- SCRAM (default): Password-based authentication
- X.509: Certificate-based authentication
- LDAP: External directory service integration
- Kerberos: Enterprise authentication system
- AWS IAM: For MongoDB Atlas with AWS integration
Troubleshooting Complex Scenarios:
1. Replica Set Authentication:
- Users must be created on primary node
- Credentials replicate to secondaries
- Use keyfile for internal authentication between nodes
- Check replica set status: rs.status()
2. Sharded Cluster Authentication:
- Users created on config servers
- Each mongos instance needs authentication configuration
- Check sharding status: sh.status()
3. MongoDB Atlas Specifics:
- Uses SCRAM-SHA-256 by default
- Network Access controls (IP whitelisting)
- Database Users vs. Organization Users
- VPC Peering and Private Endpoints
4. Docker and Containerized MongoDB:
- Environment variables: MONGO_INITDB_ROOT_USERNAME, MONGO_INITDB_ROOT_PASSWORD
- Docker secrets for password management
- Volume mounts for keyfiles and certificates
Security Best Practices:
1. Password Policies:
- Use strong, complex passwords
- Rotate passwords regularly
- Store passwords in secure vaults (not in code)
2. Connection Security:
- Always use SSL/TLS in production
- Validate server certificates
- Use VPN or VPC peering for internal traffic
3. Principle of Least Privilege:
- Grant minimum necessary permissions
- Use application-specific users, not admin accounts
- Create separate users for read-only vs read-write access
4. Monitoring and Auditing:
- Enable audit logging for authentication events
- Monitor failed authentication attempts
- Set up alerts for suspicious activity
Common Pitfalls and Solutions:
1. Special Characters in Passwords: Always URL encode passwords with special characters
2. DNS Resolution Issues: Use IP addresses if DNS is problematic
3. Time Synchronization: Kerberos and some auth mechanisms require accurate time
4. Driver Compatibility: Ensure driver version matches MongoDB version
5. Connection Pooling: Authentication happens per connection, not per pool
Diagnostic Queries:
// Check authentication configuration
db.adminCommand({getParameter: "*"})
// Check user privileges in detail
db.getUser("username", {showPrivileges: true})
// Check authentication attempts (if audit enabled)
db.system.audit.find({atype: "authenticate", "param.result": 18}) // 18 = auth failed
// Check network connections with auth status
db.currentOp(true).inprog
.filter(op => op.connectionId)
.map(op => ({
connectionId: op.connectionId,
client: op.client,
appName: op.appName,
authenticated: op.clientMetadata?.auth || "unknown"
}))When to Seek Further Help:
1. Consistent failures across all clients: Likely server-side configuration issue
2. Intermittent failures: Could be network, load balancer, or replication lag
3. Works from some locations but not others: Network/firewall/whitelisting issue
4. Works with some tools but not others: Driver or connection string format issue
Always test with multiple clients (mongosh, Compass, your application) to isolate the problem.
DivergentArrayError: For your own good, using document.save() to update an array which was selected using an $elemMatch projection will not work
How to fix "DivergentArrayError: For your own good, using document.save() to update an array which was selected using an $elemMatch projection will not work" in MongoDB
CannotCreateIndex: Cannot create index
CannotCreateIndex: Cannot create index
StaleShardVersion: shard version mismatch
How to fix "StaleShardVersion: shard version mismatch" in MongoDB
MongoOperationTimeoutError: Operation timed out
How to fix "MongoOperationTimeoutError: Operation timed out" in MongoDB
MongoServerError: PlanExecutor error during aggregation :: caused by :: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation.
How to fix "QueryExceededMemoryLimitNoDiskUseAllowed" in MongoDB