Skip to content
ohsudo, Home
Databases

MongoDB "Authentication failed": the authSource is usually what's wrong

Fix MongoDB "Authentication failed": set authSource correctly, encode special characters in the URI, check which database holds the user, and handle Docker volumes.

Beginner4 min readApplies to MongoDB 5.0+ · mongosh · Node.js driver · Docker · MongoDB Atlas

by OhSudo ··

Not sure this is your cause?Find it step by step: Can't connect to the database →

MongoServerError: Authentication failed.

The server’s reachable, and it didn’t accept these credentials. For security, the message won’t say why, and the password is only one of the reasons. The most common cause by far is authSource: a MongoDB user belongs to a particular database, and your client is looking in the wrong one.

  1. Clientuser, password, authSource
  2. Database in authSourcethe user isn't there(breaks here)
  3. Authentication failedthe user lives in admin, say
A MongoDB user belongs to one database. The client authenticates against the database in authSource; look in the wrong one, and the right password still fails.

TL;DR

Users created through the admin database need this at the end of the address:

mongodb://app:password@10.0.0.5:27017/shop?authSource=admin

Test it, without your application:

Terminal window
mongosh "mongodb://app@10.0.0.5:27017/shop?authSource=admin" --eval 'db.runCommand({ connectionStatus: 1 })'

1. Where does the user live?

This is what confuses people. A user is stored in the database it was created in. And the path in your connection string, /shop, does two jobs: it’s the default database, and if you don’t say otherwise, it’s also where the client looks for the user.

mongodb://app:password@host/shop # looks for the user in shop
mongodb://app:password@host/shop?authSource=admin # looks for the user in admin

If you made app while in admin, as is common, the first address fails with this error, and the second one works. Find the user, as an admin:

use admin
db.system.users.find({ user: 'app' }, { user: 1, db: 1, roles: 1 })

The db field is your authSource. Set it, and that’s usually all.

2. Special characters in the password

An address has its own syntax, so a password with @, : or / breaks it. These need to be percent-encoded:

Character Becomes
@ %40
: %3A
/ %2F
# %23
% %25

p@ss:word is written as p%40ss%3Aword. The URL encoder does this for you, and the Password Generator has a shell-safe option, whose passwords don’t need it. Or you can avoid the issue, by passing it separately:

Terminal window
mongosh "mongodb://10.0.0.5:27017/shop" --username app --authenticationDatabase admin --password

With no value, --password asks for it, which also keeps it out of your shell history.

3. Docker: the variables only work once

The official image creates the root user from these variables, only when the data folder is empty:

services:
mongo:
image: mongo:7
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
volumes:
- mongo:/data/db

Change the password here, on an existing volume, and nothing happens, while the old one still applies. That’s the classic case. Either change it inside, as shown in section 5, or remove the volume if there’s nothing to keep, which deletes all of its data:

Terminal window
docker compose down -v

That user is created in admin, so connect with ?authSource=admin. See also connecting to localhost from a container, since localhost in a container isn’t the other one.

4. Look at the server’s log

The server says what the client is not told:

Terminal window
docker logs mongo 2>&1 | grep -i authentic | tail -n 5
sudo grep -i authentic /var/log/mongodb/mongod.log | tail -n 5
"msg":"Authentication failed","attr":{"mechanism":"SCRAM-SHA-256","speculative":true,"principalName":"app","authenticationDatabase":"shop","error":"UserNotFound: Could not find user \"app\" for db \"shop\""}

UserNotFound with a database name is section 1. AuthenticationFailed: SCRAM authentication failed, storedKey mismatch means a wrong password.

5. Change a password

use admin
db.changeUserPassword('app', passwordPrompt())

Locked out? On your own server, restart without authentication for a moment, only on 127.0.0.1, and create the user again. In /etc/mongod.conf, set security.authorization to disabled, restart, change it, and turn it back on right away. With Docker, there’s a similar route: docker exec -it mongo mongosh connects locally.

6. Atlas

MongoDB Atlas keeps database users in its own list, under Database Access, separate from your Atlas login. Your website login won’t work here. A bad auth message means this:

MongoServerError: bad auth : Authentication failed.

Also check Network Access there, though a blocked address times out instead of giving this error.

7. It connected, and it’s not allowed

Now you’re in, and you get a different message:

MongoServerError: not authorized on shop to execute command

Authentication passed, and this user has no role on that database. Grant it:

use admin
db.grantRolesToUser('app', [{ role: 'readWrite', db: 'shop' }])

Warning

Don’t turn off authorization to fix this for good. MongoDB servers open to the internet have been emptied and held for ransom by the thousands. Keep authorization: enabled, bind to a private address, and don’t publish 27017. The Port Lookup has an entry on that.

Shell, we have a problem!

Similar, but different: connect ECONNREFUSED means you never reached the server. not authorized means you’re in, without rights. Server selection timed out is usually the network, or a firewall. And a refused write is often E11000.

Found this useful? Share it.

Found a mistake? Let us know at contact@ohsudo.com.

Tools

Try it yourself

Articles

Related articles