【Next.js】ログインできない原因7選と解決方法(Firebase対応)

Webアプリを作っていると、ほぼ確実にぶつかる問題があります。

「ログインできない」問題。

・パスワードは合っているはず
・サーバーは動いている
・エラーも出ていない

それでもログインできない。

この記事では、初心者でも理解できるように

  • ログインが動く仕組み
  • よくある原因
  • 実際のデバッグ方法
  • 本番環境で起きやすい罠

を順番に解説します。


まず理解するべきこと:ログインの仕組み

ログインは大きく分けて4ステップです。

  1. フロントエンドがID・パスワードを送る
  2. サーバーが認証する
  3. セッション or トークンを発行する
  4. ブラウザがそれを保存する

このどこかが壊れると、ログインできません。


よくある原因 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 でない環境で有効になっている。


③ cookieの設定ミス(Render・Vercelで多発)

よくある地雷

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つが成立すれば動きます。


まとめ

ログインできない時は、

  1. DB確認
  2. bcrypt確認
  3. cookie確認
  4. session保存確認
  5. 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の理解”が重要なのです。

おすすめの記事