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.
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.
- Clientuser, password, authSourcelooks in
- Database in authSourcethe user isn't there(breaks here)not found(fails)
- Authentication failedthe user lives in admin, say
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=adminTest it, without your application:
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 shopmongodb://app:password@host/shop?authSource=admin # looks for the user in adminIf 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 admindb.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:
mongosh "mongodb://10.0.0.5:27017/shop" --username app --authenticationDatabase admin --passwordWith 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/dbChange 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:
docker compose down -vThat 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:
docker logs mongo 2>&1 | grep -i authentic | tail -n 5sudo 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 admindb.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 commandAuthentication passed, and this user has no role on that database. Grant it:
use admindb.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.