Next.js App router セキュリティで気をつけること
はじめに
Next.jsのApp routerは、server components/server actionsによって、フロントエンドとバックエンドを型安全にやり取りでき、開発体験がとても良いですよね。
しかし、フロントエンドとバックエンドの境目がわかりづらくなったので、何も考えずに実装していると、フロントエンドにセキュアな情報が露出してしまうリスクが高まります。
そこで今回は、App routerを使う中で、セキュリティで気をつけることを紹介します。
先に言うと、フロントエンドとバックエンドの境目に気を遣えば基本良いかなと思います。
クライアントコンポーネントのpropsを本当に必要な情報だけにする
App routerでは、
サーバーコンポーネントでデータ参照 → クライアントコンポーネントはprops経由でデータを取得してUI表示
をする流れが多いです。
クライアントは、サーバーのデータをpropsで受け取れてしまうので、props経由で受け取るデータを気をつける必要があります。
例えば、めんどくさくてクライアントで受け取るpropsのデータの型を、サーバー側で扱ってるデータの型と同じにしてしまうと、クライアントに見せたくないデータまでクライアントに渡してしまうリスクがあります。
このようなリスクを避けるために、propsは本当に必要なデータのみに限定しましょう。
サーバー専用ファイルには、server-onlyをつける
App routerでは、サーバー専用ファイルもクライアント専用のファイルも、同じプロジェクトで混在します。
なので、間違えてクライアント専用ファイルでサーバー専用のファイルをimportしてしまうリスクがあります。
基本はサーバーの処理はクライアントで実行できないのでエラーが出るはずですが、クライアントにサーバー専用のコードが漏れるリスクもあります。
これを解決する方法があります。server-onlyをつけます。
server-onlyをつけたファイルをクライアントコンポーネントでimportすると、ビルドエラーが出ますので、importしたままでデプロイすることが防げます。
以下のようにして、server-onlyをつけます。
import 'server-only';
export async function getUser (id: string) {
// 色々処理
}
Server Actionsの使い方を気をつける
Server Actionsは、Next.jsのApp Routerで使える新しい機能です。
この機能を使うと、クライアントコンポーネントの中で直接サーバーサイドの処理を呼び出せます。一見便利そうですが、Server Actionsの実態はAPIでかつ、クライアントに漏れ出るサーバー処理になります。
ですので、使い方次第ではセキュリティに悪影響を及ぼす可能性があります。
これに対しては、以下を気をつければOKです。
無闇にServer Actionsを使わない
Server Actionsはとても便利ですが、クライアントに漏れてしまうので、何でもかんでもServer Actionsにすると危険です。
本当に必要なサーバー処理だけをServer Actionsにして、それ以外はサーバーコンポーネント等に書きましょう。
Server Actions内で認証/認可チェックなどをして悪用を防ぐ
Server Actionsは、クライアントに漏れているサーバー処理なので、外部から悪用されないために、処理の初めに認証/認可チェックを入れると良いです。
APIを開発する時と同じような考えで、認証/認可チェックをして、不正な場合は早期リターンやエラーをスローするようにすると良いでしょう。
ついでに言うと、Server Actionsは、ユーザー操作を伴う処理が多いので、最終的にはエラートーストを出してあげた方が優しいです。
環境変数はなるべくpublicにしない
Next.jsに限った話ではないですが、環境変数はなるべくpublicなものにしないようにしましょう。
publicな環境変数は、クライアントに露出しますが、publicでない場合はサーバーコンポーネントでしか取得することはできません。
以下のイメージです
// .env
SECRET_ENV= ← サーバーコンポーネントでしか取得できない
NEXT_PUBLIC_ENV= ← クライアントでも取得できる
エラーメッセージに気を遣う
これもNext.jsに限った話ではないですが、DBの構成がわかってしまうようなエラーメッセージをエラーページに表示しないよう心がけましょう。
例えば、DB操作系の処理で、DBの構成がわかってしまうようなエラーメッセージは表示しない方が良いです。
エラーメッセージでDBの構成の一部がわかってしまい、攻撃されてしまうなどと言うことが考えられます。
従来の開発では、API経由でフロントはエラーメッセージを取得するので、あんまりDBの構成がわかってしまうようなエラーメッセージを表示することはないかと思います。
しかし、App routerだと、クライアントとサーバーの境目がわかりにくいため、このようなパターンを踏んでしまう可能性が従来より高いと考えられますので、気をつけましょう。
まとめ
以上です。
基本的には、App routerにおける、クライアントとサーバーの境目を理解し、そこでセキュアな情報が漏れてないか気をつけることが大事だと考えています。
Discussion