webアプリのログイン認証
この2連休は、新ピクチャレ大会にログイン認証を実装する作業にすべてを捧げました。
寝ている以外のほとんどの時間を費やし、日曜日の26時についにログイン通過。
この紆余曲折はぜひQiitaにでも書いて共有したいところではありますが、
経緯を丁寧に書いているとそれだけでまた数日潰れるのでブログで勘弁してください。
まず、要件として今回のログイン機能はフロントエンドがNext.js、
バックエンドがLaravelでそれぞれをDockerが仮想コンテナ上に構築している、
という前提のもと、名前とパスワードのみ登録していた前サービスを引き継ぐ必要がありました。
そこで最初に取り掛かったのがLaravelが提供する「Laravel Breeze」というライブラリ。
これを導入すればすごく簡単にログイン認証をつけられるというもので、
実際に2020年にLaravelの研修を受けた際にもできた記憶があるので、
まあこれが無難だろと思って着手しました。が、丸一日かけても実装することはできませんでした。
その主な要因は2つ。
まず、Laravel Breezeは基本的にLaravelで完結するwebアプリを想定していること。
つまり、フロントエンドもLaravelのBlade等で表示する想定の構造になっているということです。
もちろんそのBladeをReact等に置き換えることはできなくはないのですが、
今回のプロジェクトは表示部分とAPI部分をコンテナから分離してしまったため、
Laravelで構築したサービスを運用するためにはどうしたってAPIを通さなければなりません。
Laravel Breezeの内部構造を見るとAPIではないルートにもアクセスするよう定義されていて、
ここにアクセスできるようにいまから改修するのは非常に難しい。
というか自分にできるのかという問題が。
もうひとつは、LaravelコンテナとNextコンテナはそれぞれ別のネットワークなので、
これを両者間で認証情報を伴う通信を開通させるのが非常に難しい。
言うなれば異なるコンテナはそれぞれ見知らぬ人が運営するサイトのようなものなので、
当然簡単に相互書き込みできないようにネットワーク上のルールが決められています。
その例外を作ってトンネルを開けるのですが、
Dockerだとこっちから見るとlocalhostなのにあっちからは全然違うIPだったりしてややこしい。
結局これで匙を投げて、別のライブラリを探すことにしました。
それまででも結構な作業時間を費やしていたので損切りには勇気が要りました。
次に試したのは「Next-Auth」。つまり、今度はフロントエンド側のライブラリ。
簡単にSSO(シングルサインオン)を構築できるなどハードルの低さが売りみたいで、
もちろんパスワード認証にも対応している。
これは期待できるぞと思っていざ着手してみると、
公式のドキュメントがあまりにも少ないことに気づきました。
公式はパスワード認証を「非推奨」としており、なるべく使ってほしくない意図があるそうです。
なのでいちおう機能としては用意するけど、パスワードの保存先や暗号化は自前で実装してね、
ということらしい。なんてこった。
しかし世界は広いもので、自前でフルスタックのNext-Auth製パスワード認証機能を作った猛者が、
Githubに全ソースを公開していたのでそれを参考に作ることにしました。
パスワードの保存先は最近流行りのクラウドサービスに頼るという手もありましたが、
既存のMySQLサーバーを流用できる「Prisma」というライブラリに頼ることにしました。
これはざっくり言うとフロントエンド側でデータベースの中身を操作できるライブラリです。
具体的にはデータの読み書きはもちろん、テーブルの作成や定義、初期値の入れ込みなど、
Laravelでできる基本的なことはシンプルにできるようになっています。
あまりにもあっさりできたので、
「これもうLaravel要らないんじゃね?」と思わずにいられませんでした。
ただそこから先は苦行でした。無料公開していたGithubのオープンソースも結構ガバガバで、
とにかく押しても引いてもエラーが出る。そのたびにエラーの内容を検証しては次に進む。
2日目の夜からはChatGPTにも頼ってひたすらエラーをつぶしまくりました。
そして苦節30時間(推定)、ついにログインに成功!
いやー、webプログラミングでここまでの達成感を味わったのはひさびさな気がする。
この2日だけでDevToolsの使い方を始め、かなり問題解決能力は上がったと思います。
あとやっぱりプログラミング分野に関してはChatGPTは有能ですね。
「この情報群のどこかに答えはあるんだけどその探し方がわからない」
といった場合にソースコードとエラーメッセージを投げると結構的確に答えてくれました。
割と真面目にChatGPTが自分にとってのメンターになりうると思っています。
いままではエラーが出たら「エラーメッセージでググる」「公式ドキュメントを読む」
といった程度が関の山でしたが、
今回の試行錯誤を経て「ロガーを仕込む」「ネットワークログを読み解く」
といった手法も開拓しました。
特に後者はコンソールでエラーが出ていない場合もエラーが表示されている場合があり、
非同期通信などを伴う処理ではチェックは必須と言って良さそうです。
残り時間がどんどん少なくなってきて少しずつ焦りも出てきたピクチャレ大会開発ですが、
ひとまず最大の山場(?)を越えられたのはなによりです。
あと1つ大型のタスクを残しているのですが、それが今回よりキツくないことを祈っています……。