初めてのNestJS :iOS/Androidアプリの管理ウェブアプリ作成奮闘記
モバイルアプリに対する管理ウェブアプリを以下の構成で作成中。
- フロントエンド:Next.js
- バックエンド:NestJS
- インフラ:firebase
特に今回、NestJSとfirebaseは初めて使う技術である。作成過程で試行錯誤した記録を残していく。
Guardでハマった話
認証基盤にはfirebase Authenticationを使用。
Next.js側でユーザーが入力したメアドとパスワードを受け取りNestJS側で作成した/signin
をPOSTを叩くまでは何とかなったが、そのままPR出したら「ログイン後のAPIにはAuthGuardを使って不正なアクセスを防ぐ必要があります。」というアドバイスをもらった。
バックエンド開発の知見がフロントに比べると浅く「Guardって何?」というところから始まったので「NestJS Guard」とかでググってみた。
するとまずGuard自体は
ガードには単一責任性があります。実行時に存在する特定の条件(パーミッション、ロール、ACLなど)に応じて、リクエストがルートハンドラーによって処理されるかどうかを決定します。これは認可(authorization)と呼ばれます。認可(や通常はそれと連携する認証(authentication))は通常は、従来のExpressアプリケーションのミドルウェアによって処理されてきました。ミドルウェアは認証に適した選択肢です。トークンの検証やrequestオブジェクトへのプロパティの添付などが、特定のルートコンテキスト(およびそのメタデータ)と強く結びついていないためです。
[参考:https://qiita.com/mana-vv/items/1c975573516eeefa92b3]
と記載があり、要は「認可に特化したミドルウェア」くらいの理解で進むことにした。
ではそのGuardをどうやって実装するのかで「NestJS AuthGuard」とかでググったが、だいたい以下の記事で書かれているようなJWTを用いた方法が紹介されていたため自分のコードにチューニングしながら書いてみた。
※記事は古いが他記事も概ね似たようなことが書かれていた。
しかし、いざGuardを組み込んで動作確認を行うと、例えばフロント側でユーザー一覧をGETするAPI(/users
)を呼び出したところ accessTokenがあってもなくても適当な文字列に置き換えても値が取得できてしまうという溝にハマってしまった。
これではセキュリティガバガバで先に進めない。きちんと認可を設定しないといけない。
とりあえず基礎に立ち返りフロント側のAPIリクエストヘッダーに
- 正しいaccessTokenを組み込んでリクエスト→200レスポンスが返ってくる。
- 不正なaccessTokenを組み込んでリクエスト→401(Unauthorized)レスポンスが返ってくる。
- accesTokenなしでリクエスト→401(Unauthorized)レスポンスが返ってくる。
という状態を目指して試行錯誤し始めた。