TL;DR
You're hitting MongoServerError: Authentication failed because either the credentials are wrong, the user doesn't exist in the expected database, or you're missing the authSource parameter. The fastest fix:
# Test connection with explicit authSource
mongosh "mongodb://username:password@host:27017/mydb?authSource=admin"
If that works, update your connection string and move on. If not, keep reading.
What Triggers This Error
MongoDB authenticates users against a specific database โ the authentication database. When the credentials you provide don't match what's stored there, you get:
MongoServerError: Authentication failed.
This shows up in mongosh, Node.js (Mongoose/mongodb driver), Python (PyMongo), and any other MongoDB client. The root cause is almost always one of these:
- Wrong username or password
- User was created in a different database than where you're authenticating
authSourcenot specified โ defaults to the connection database, notadmin- Auth mechanism mismatch (SCRAM-SHA-1 vs SCRAM-SHA-256)
- User doesn't exist at all
Fix 1: Check the Authentication Database (authSource)
This is the #1 cause โ it accounts for the majority of authentication failures. MongoDB users are scoped to the database they were created in. If your user lives in admin but your connection string omits authSource=admin, MongoDB looks for that user in the target database instead. It won't find them, and it fails.
# Wrong โ tries to auth against 'mydb', not 'admin'
mongosh "mongodb://admin:secret@localhost:27017/mydb"
# Correct โ explicitly authenticate against 'admin'
mongosh "mongodb://admin:secret@localhost:27017/mydb?authSource=admin"
In Node.js with the MongoDB driver:
const client = new MongoClient('mongodb://localhost:27017', {
auth: { username: 'admin', password: 'secret' },
authSource: 'admin',
});
In Mongoose:
mongoose.connect('mongodb://localhost:27017/mydb', {
user: 'admin',
pass: 'secret',
authSource: 'admin',
});
In PyMongo:
from pymongo import MongoClient
client = MongoClient(
host='localhost',
port=27017,
username='admin',
password='secret',
authSource='admin'
)
Fix 2: Verify the User Actually Exists
Before resetting passwords, confirm the user is there at all. Log in with a known admin account and check:
# Connect as admin first
mongosh -u root -p --authenticationDatabase admin
# Then switch to the target database and list users
use mydb
db.getUsers()
# Or check all users in admin
use admin
db.system.users.find({}, { user: 1, db: 1 }).pretty()
If the user is missing, create them:
use mydb
db.createUser({
user: "appuser",
pwd: "strongpassword",
roles: [{ role: "readWrite", db: "mydb" }]
})
Fix 3: Reset the Password
User exists but you're not sure the password is right? Reset it from an admin session rather than guessing:
# Connect as admin
mongosh -u root -p --authenticationDatabase admin
# Reset password
use mydb
db.updateUser("appuser", { pwd: "newstrongpassword" })
Then test immediately:
mongosh -u appuser -p newstrongpassword --authenticationDatabase mydb
Fix 4: Check the Auth Mechanism
MongoDB 4.0+ defaults to SCRAM-SHA-256, but older drivers or legacy configs may still negotiate SCRAM-SHA-1. You can force a specific mechanism to rule this out:
# Force SCRAM-SHA-1 if needed
mongosh "mongodb://user:pass@host:27017/db?authSource=admin&authMechanism=SCRAM-SHA-1"
To check which mechanisms a user supports:
use admin
db.system.users.find({ user: "appuser" }, { mechanisms: 1 })
If mechanisms only shows SCRAM-SHA-1 but your driver requests SCRAM-SHA-256, update the user to support both:
db.updateUser("appuser", {
pwd: "yourpassword",
mechanisms: ["SCRAM-SHA-1", "SCRAM-SHA-256"]
})
Fix 5: Escape Special Characters in the Connection String
Passwords containing @, :, /, #, or ? silently break connection string parsing if not percent-encoded. The parser splits the URL on those characters before your credentials even reach MongoDB. A password like p@ss:word must become p%40ss%3Aword.
# Broken โ '@' in password splits the connection string
mongodb://user:p@ss:word@host:27017/db
# Fixed โ percent-encode special chars
mongodb://user:p%40ss%3Aword@host:27017/db
In Node.js, use encodeURIComponent() on the password before building the URI. In Python, use urllib.parse.quote_plus(). Or skip inline credentials entirely and pass them as separate driver options โ that sidesteps encoding issues completely.
Verification Steps
After any fix, confirm things are actually working before shipping:
# Direct connection test
mongosh "mongodb://appuser:password@localhost:27017/mydb?authSource=mydb"
# Run a quick query to confirm read access
db.runCommand({ connectionStatus: 1 })
# Look for: "authenticated" : true
For application-level verification, add a connection check at startup:
// Node.js
client.connect().then(() => {
return client.db('admin').command({ ping: 1 });
}).then(() => console.log('Auth OK'))
.catch(err => console.error('Auth failed:', err.message));
Prevention Tips
Most of these failures are avoidable with a few consistent habits:
- Always specify
authSourceexplicitly in connection strings โ never rely on the default. - Store MongoDB credentials in environment variables, not hardcoded in source code.
- Use strong, randomly generated passwords. If you need one, ToolCraft's Password Generator runs entirely in your browser with no data uploaded โ useful for generating credentials without leaking anything.
- Document which database each user was created in. Three months later, nobody remembers.
- Test credentials immediately after creating or rotating users โ not during an outage.

