TL;DR
MongoServerError: Authentication failed が発生する原因は、認証情報の誤り、ユーザーが想定するデータベースに存在しない、または authSource パラメータが指定されていないことがほとんどです。最速の解決策:
# authSourceを明示して接続テスト
mongosh "mongodb://username:password@host:27017/mydb?authSource=admin"
これで接続できれば、接続文字列を更新して完了です。できない場合は読み続けてください。
このエラーが発生する原因
MongoDBはユーザーを特定のデータベース(認証データベース)に対して認証します。提供した認証情報がそこに保存されているものと一致しない場合、以下のエラーが発生します:
MongoServerError: Authentication failed.
このエラーはmongosh、Node.js(Mongoose/mongodbドライバー)、Python(PyMongo)、その他のMongoDBクライアントで表示されます。根本原因はほぼ常に以下のいずれかです:
- ユーザー名またはパスワードが間違っている
- ユーザーが認証しようとしているデータベースとは別のデータベースで作成されている
authSourceが未指定 — デフォルトはadminではなく接続先データベース- 認証メカニズムの不一致(SCRAM-SHA-1 vs SCRAM-SHA-256)
- ユーザーが存在しない
修正1:認証データベース(authSource)を確認する
これが最も多い原因で、認証失敗の大半を占めます。MongoDBのユーザーは作成したデータベースにスコープされています。ユーザーが admin にいるのに接続文字列に authSource=admin がない場合、MongoDBは接続先データベースからユーザーを探します。見つからないため、認証が失敗します。
# 間違い — 'admin' ではなく 'mydb' で認証しようとする
mongosh "mongodb://admin:secret@localhost:27017/mydb"
# 正しい — 'admin' に対して明示的に認証する
mongosh "mongodb://admin:secret@localhost:27017/mydb?authSource=admin"
MongoDBドライバーを使用するNode.jsの場合:
const client = new MongoClient('mongodb://localhost:27017', {
auth: { username: 'admin', password: 'secret' },
authSource: 'admin',
});
Mongooseの場合:
mongoose.connect('mongodb://localhost:27017/mydb', {
user: 'admin',
pass: 'secret',
authSource: 'admin',
});
PyMongoの場合:
from pymongo import MongoClient
client = MongoClient(
host='localhost',
port=27017,
username='admin',
password='secret',
authSource='admin'
)
修正2:ユーザーが実際に存在するか確認する
パスワードをリセットする前に、そもそもユーザーが存在するか確認しましょう。既知の管理者アカウントでログインして確認します:
# まず管理者として接続
mongosh -u root -p --authenticationDatabase admin
# 対象データベースに切り替えてユーザー一覧を確認
use mydb
db.getUsers()
# またはadmin内の全ユーザーを確認
use admin
db.system.users.find({}, { user: 1, db: 1 }).pretty()
ユーザーが存在しない場合は作成します:
use mydb
db.createUser({
user: "appuser",
pwd: "strongpassword",
roles: [{ role: "readWrite", db: "mydb" }]
})
修正3:パスワードをリセットする
ユーザーは存在するがパスワードが正しいか不明な場合、推測するより管理者セッションからリセットしましょう:
# 管理者として接続
mongosh -u root -p --authenticationDatabase admin
# パスワードをリセット
use mydb
db.updateUser("appuser", { pwd: "newstrongpassword" })
その後すぐにテストします:
mongosh -u appuser -p newstrongpassword --authenticationDatabase mydb
修正4:認証メカニズムを確認する
MongoDB 4.0以降はデフォルトでSCRAM-SHA-256ですが、古いドライバーやレガシー設定ではSCRAM-SHA-1でネゴシエートする場合があります。問題を切り分けるために特定のメカニズムを強制指定できます:
# 必要に応じてSCRAM-SHA-1を強制指定
mongosh "mongodb://user:pass@host:27017/db?authSource=admin&authMechanism=SCRAM-SHA-1"
ユーザーがサポートするメカニズムを確認するには:
use admin
db.system.users.find({ user: "appuser" }, { mechanisms: 1 })
mechanisms に SCRAM-SHA-1 しかないのにドライバーが SCRAM-SHA-256 を要求している場合、両方サポートするようユーザーを更新します:
db.updateUser("appuser", {
pwd: "yourpassword",
mechanisms: ["SCRAM-SHA-1", "SCRAM-SHA-256"]
})
修正5:接続文字列の特殊文字をエスケープする
@、:、/、#、? を含むパスワードはパーセントエンコードしないと、接続文字列のパースが静かに壊れます。パーサーが認証情報をMongoDBに渡す前にURL上でこれらの文字で分割してしまうためです。p@ss:word のようなパスワードは p%40ss%3Aword にする必要があります。
# 誤り — パスワードの '@' が接続文字列を分割してしまう
mongodb://user:p@ss:word@host:27017/db
# 正しい — 特殊文字をパーセントエンコードする
mongodb://user:p%40ss%3Aword@host:27017/db
Node.jsではURIを組み立てる前にパスワードに encodeURIComponent() を使います。Pythonでは urllib.parse.quote_plus() を使います。または、インラインの認証情報を使わずドライバーのオプションとして別途渡す方法もあり、エンコードの問題を完全に回避できます。
動作確認の手順
修正後は、リリースする前に正常に動作していることを確認しましょう:
# 直接接続テスト
mongosh "mongodb://appuser:password@localhost:27017/mydb?authSource=mydb"
# 読み取りアクセスを確認するクエリを実行
db.runCommand({ connectionStatus: 1 })
# 確認ポイント: "authenticated" : true
アプリケーションレベルの確認では、起動時に接続チェックを追加します:
// Node.js
client.connect().then(() => {
return client.db('admin').command({ ping: 1 });
}).then(() => console.log('認証OK'))
.catch(err => console.error('認証失敗:', err.message));
予防策
いくつかの一貫した習慣を守ることで、これらの障害のほとんどは回避できます:
- 接続文字列には常に
authSourceを明示的に指定する — デフォルト値に依存しない。 - MongoDBの認証情報はソースコードにハードコードせず、環境変数に保存する。
- 強力でランダムに生成されたパスワードを使用する。必要な場合は、ToolCraftのパスワードジェネレーターがブラウザ上で完結し、データは一切アップロードされないため、情報漏洩なしに認証情報を生成できます。
- 各ユーザーがどのデータベースで作成されたかドキュメント化する。3ヶ月後には誰も覚えていない。
- ユーザーの作成やローテーション後は、障害発生時ではなくすぐに認証情報をテストする。

