
Webアプリを作っていると、ほぼ確実にぶつかる問題があります。
「ログインできない」問題。
・パスワードは合っているはず
・サーバーは動いている
・エラーも出ていない
それでもログインできない。
この記事では、初心者でも理解できるように
- ログインが動く仕組み
- よくある原因
- 実際のデバッグ方法
- 本番環境で起きやすい罠
を順番に解説します。
Contents
まず理解するべきこと:ログインの仕組み
ログインは大きく分けて4ステップです。
- フロントエンドがID・パスワードを送る
- サーバーが認証する
- セッション or トークンを発行する
- ブラウザがそれを保存する
このどこかが壊れると、ログインできません。
よくある原因 7選
① パスワード比較ミス(bcrypt関連)
多いです。
bcrypt.compare(plainPassword, hashedPassword)
順番が逆になっていませんか?
よくあるミス
- compareをawaitしていない
- saltRoundsが違う/hash化されていない文字列をcompareしている
- Firestoreに保存された値が違う
確認方法
console.log("input:", password)
console.log("db:", user.password)
まずは「本当に一致しているか」を確認。
② セッションが保存されていない
特に本番環境で多い。
症状
- ログイン成功レスポンスは返る
- でも次のページで未ログイン扱い
原因はこれ。
req.session.save()
これを呼んでいない。
または、
cookie: {
secure: true
}
これが https でない環境で有効になっている。
よくある地雷
app.set("trust proxy", 1)
これがないと secure cookie が保存されません。
RenderやVercelなど、プロキシ経由で動く環境では必須。
④ CORS設定ミス
フロントとAPIのドメインが違う場合。
必須設定
credentials: true
そして
fetch("/api/login", {
method: "POST",
credentials: "include"
})
これがないとcookieは送られません。
⑤ bodyが送られていない
実は多い。
fetch("/api/login", {
method: "POST"
})
bodyがない。
または
headers: {
"Content-Type": "application/json"
}
これを付け忘れている。
⑥ Firestoreのデータ構造が違う
例:
profile: {
email: ""
}
と思っていたら
email: ""
になっている。
→ 取得できない → ログイン失敗
console.logでDB構造を必ず確認。
⑦ Edge Runtime問題(Next.js特有)
Next.js App Router使用時。
APIルートに
export const runtime = "nodejs"
を書いていないと、
- セッションが壊れる
- Firebase adminが動かない
デバッグ手順(初心者向け)
STEP1:Networkタブを見る
Chrome DevTools → Network → loginリクエスト
確認すること:
- Statusは200か?
- responseは何?
- Cookieは付いているか?
STEP2:サーバー側にconsole.logを置く
console.log("session before:", req.session)
これで保存されているか確認。
STEP3:/session APIを作る
app.get("/session", (req, res) => {
res.json(req.session)
})
これで現在のログイン状態を可視化できる。
本番環境で起きやすいトラブル
| 症状 | 原因 |
|---|---|
| ローカルでは動く | secure cookie |
| 本番でのみログイン不可 | trust proxy |
| リロードすると未ログイン | session未保存 |
| 一瞬ログインしてすぐ消える | cookie maxAge問題 |
ログイン問題の本質
ログインは
「状態を保持できるか」
これだけです。
・サーバーが状態を保存する
・ブラウザがそれを持ち続ける
この2つが成立すれば動きます。
まとめ
ログインできない時は、
- DB確認
- bcrypt確認
- cookie確認
- session保存確認
- Networkタブ確認
この順で潰していけば必ず原因は見つかります。
Procomでも実際に起きたログイン不具合
ここからは、実際に私が開発している Procom(Next.js + Firebase + Render本番環境) で発生したリアルなログイントラブルを紹介します。
理論ではなく、実際に詰まったポイントです。
① Render本番環境でセッションが保持されない
症状
- ログインAPIは成功する
- 200が返る
- しかし
/sessionを叩くとloggedIn: false - ページ遷移すると未ログイン扱い
ローカルでは正常。
本番だけ壊れる。
原因
secure: true
を設定しているのに、
app.set("trust proxy", 1)
を設定していなかった。
Renderのようなプロキシ環境ではtrust proxy がないと secure cookie が保存されません。
解決策
app.set("trust proxy", 1)
を追加。
これでcookieが正しく保存され、ログイン状態が保持されました。
② req.session.save() を呼んでいなかった
症状
- ログイン直後は一瞬ログイン状態
- すぐ消える
原因
req.session.username = user.username
だけで満足していた。
しかし、保存処理がなかった。
解決策
req.session.save(() => {
res.json({ success: true })
})
これを入れたら安定。
セッションは代入しただけでは保存されません。
③ username → uid 移行でログイン不能
Procomでは途中から
usernameベース管理 → uidベース管理
に変更しました。
症状
- ログインは成功
- しかしユーザーページが取得できない
- API
/api/user/:usernameが404
原因
FirestoreのドキュメントIDは uid なのに、
req.session.username
を参照していた。
つまり、
「ログイン情報」と「取得キー」が一致していなかった。
解決策
- セッションに
uidを保存 - 全APIを
uid基準に統一
ログイン系は キーの統一が最重要。
④ Edge Runtimeの罠(Next.js)
App RouterでAPIを作った際、
params.uid 警告
が出ていた。
最初は無視していた。
症状
- Firebase admin が不安定
- セッションが壊れる
- なぜか動いたり動かなかったりする
原因
APIルートがEdge Runtimeで動いていた。
Firebase adminはNode環境が前提。
解決策
export const runtime = "nodejs"
を追加。
これで安定。
⑤ Firestore保存エラーでログインが壊れた
一見関係なさそうですが、
Property profile contains an invalid nested entity
エラーが発生。
原因
calendarEvents: []
や undefined が保存データに含まれていた。
Firestoreは undefined を許可しない。
保存エラー → プロフィール壊れる → ログイン後取得失敗
解決策
保存前に整形:
Object.fromEntries(
Object.entries(obj).filter(([_, v]) => v !== undefined)
)
ログイン不具合の原因が「保存エラー」だった例です。
⑥ credentials: "include" を忘れていた
Next.js側で
fetch("/api/login")
だけ書いていた。
症状
- ログイン成功レスポンスは返る
- でもcookieが保存されない
解決策
fetch("/api/login", {
method: "POST",
credentials: "include"
})
これを入れた瞬間に解決。
実体験から分かったこと
ログインできないとき、多くの人は「パスワードが違う」と思います。
しかし実際は「状態が保存されていない」ケースがほとんどです。つまり、認証よりも“セッションとCookieの理解”が重要なのです。








