Beszel認証エラーの犯人は「未認証メール」と「隠れたログ」

Progress 12 / 18
目次

Beszelの認証にPocket ID(OIDC)を導入しようとして、見事に泥沼にハマってしまいました。 「設定は合っているはずなのに動かない」「ログにも何も出ない」という、エンジニアなら誰もが一度は経験するあの絶望感……。

今回は、そんな状況から1時間の徒労を経て見つけた「真犯人」と、そこから得た教訓をシェアしたいと思います。

謎の認証エラー

事の発端は、軽量サーバー監視ツールであるBeszelに、OIDCプロバイダーとしてPocket IDを連携させようとしたことでした。 ドキュメント通りクライアントID/シークレットを登録し、いざログイン!と意気込んだものの……。

ブラウザには真っ暗な画面が表示されるだけ。 開発者ツールを見ても、返ってきているのは一般的な 400 Bad Request401 Unauthorized ばかりで、具体的な理由は書かれていません。

「まあ、ログを見れば分かるだろう」 そう思ってPodの標準出力を確認しました。

Terminal window
kubectl logs -f pod/beszel-xyz -n monitor

しかし、そこには何も表示されていなかったのです…。 ログイン試行の形跡すらありません。

疑心暗鬼の1時間

ここからが迷走の始まりでした。 「アプリにリクエストが届いていないのでは?」と考え、疑いの目はリバースプロキシであるTraefikに向けられました。

  • Middlewareの設定がおかしいのか?
  • ヘッダーが削除されている?
  • Gzip圧縮が悪さをしている?

疑心暗鬼はこれだけにとどまりません。「Client IDやSecretが間違っているのかも?」と疑って何度も再生成してみたり、「既存のアカウントと重複して紐付けに失敗しているのか?」と考えてアカウントを作り直してみたり……。

全く関係のない圧縮設定まで調べ回り、「なぜだ……」と頭を抱えること1時間。 結局、Traefikの設定も認証情報も、何も間違っていませんでした。

真犯人は「未認証のメールアドレス」

解決の糸口は、ふと思い立ってBeszel(実体はPocketBase)の管理画面や内部DBを直接確認しようとしたことでした。

PocketBaseには ログを標準出力ではなく、内部のDBに保存するという仕様(設定)があったのです。 そこを確認して、ようやく真のエラーメッセージにたどり着きました。

“Email cannot be empty”

……え?空?

原因のメカニズム

原因は、Pocket ID側で作成したユーザーの 「Email Verification(メールアドレス確認)」が済んでいなかったことでした。そもそもSelf Hostedでメールサーバーを立てていないので、メールの認証をするとかは全く思考にない状態です。

  1. Pocket IDは、メール確認が未完了のユーザー情報をOIDCで送る際、email フィールドは値が入っていても email_verified: false というステータスを返します。
  2. 一方、BeszelのバックエンドであるPocketBaseのOIDC処理は、email_verifiedfalse の場合、そのメールアドレスを信頼できないもの(または無効なもの)として扱い、内部的にEmailを空として処理しようとした、あるいはバリデーションではじいた可能性があります。
  3. その結果、PocketBaseが「メールアドレスがないじゃないか!(正確には、使えるメールアドレスがない)」と怒ってエラーを返していたのですが、その叫びは標準出力には届かず、内部DBの中にひっそりと書き込まれていたのでした。

OIDC認証を行う場合、IDプロバイダー側で属性情報(特にメールアドレス)が確実に提供される状態、かつ 有効な状態(Verified) になっているか、注意が必要です。

Pocket IDの場合は管理画面に確認済にするボタンがあり、そこから管理者権限で強制的に認証状態へ変更することが可能です。これによりEmailを正しく連携することができるようになります。

教訓:ログがないを信じるな

今回の教訓はこれに尽きます。

「Podの標準出力にログがないからといって、アプリケーションがエラーを吐いていないとは限らない」

「ログは標準出力に出す」のがコンテナの作法とされていますが、すべてのアプリがそれに従っているわけではありません。特にDB内蔵型のアプリや、パフォーマンスを重視した設計のアプリでは、ログの出力先がファイルやDBになっていることがあります。

「起動ログしか出ていないのはどういう了見だ!」と叫びたくもなりますが、そこはぐっとこらえて。 標準出力が沈黙しているときは、アプリケーション固有のログ仕様や、管理画面内のログビューワーを確認してみるのが吉です。

今回のハマり記録が、同じように「沈黙するコンテナ」の前で立ち尽くしている誰かの助けになれば幸いです。