機能このページを編集.md

サーバ関数の暗号化

@lazarv/react-serverはデフォルトですべてのサーバー関数識別子をAES-256-GCMを使用して暗号化します。これにより、レンダリング時に明示的に公開されていないサーバ関数をクライアントが発見したり呼び出したりすることを防止します。

暗号化を行わない場合、サーバー関数識別子は平文の文字列であり、ソースファイルのパスや関数名(例: src/actions#deleteUser)を露呈します。これにより、クライアントは任意のリクエストを作成し、アプリケーション内のあらゆるサーバ関数を呼び出すことが可能になります。これは、そのユーザーに対してレンダリングされたことのない関数であっても同様です。暗号化により、レンダリング時にサーバーから返されたサーバ関数のみが呼び出し可能となります。

サーバ関数トークンは2つのタイプがあります。

インライントークンは、サーバ関数参照が初めて使用された際に生成されます。暗号化されたトークンは関数インスタンスにキャッシュされ、Reactの内部フォーム状態マッチング(例:useActionState)が正しく動作するようにします。インラインサーバ関数およびクライアントコンポーネントにプロップとして渡されるサーバ関数は、RSCストリームに埋め込まれたこれらのトークンを使用します。

静的トークンは、ビルド時(または開発時のVite変換時)にサーバ関数モジュール(最上位に"use server"を含むファイル)に対して生成されます。これらのトークンはクライアント用JavaScriptバンドルに埋め込まれ、クライアントコンポーネントがサーバ関数を直接インポートする際に使用されます。

両方のタイプは同じ鍵で暗号化され、サーバ関数が呼び出された際にサーバー上で透過的に復号化されます。

暗号化は設定不要でそのまま動作します。

これはサーバ関数の暗号化が常に有効であることを意味します。独自の秘密鍵を提供したい場合や鍵のローテーションを有効にしたい場合にのみ設定が必要です。

環境変数またはランタイム設定を使用して独自の暗号化シークレットを提供できます。これは、デプロイを跨いで決定論的なキーが必要な場合や、複数のサーバーインスタンスを実行する場合に有用です。

シークレットは次の優先順位で解決されます。

  1. REACT_SERVER_FUNCTIONS_SECRET 環境変数
  2. REACT_SERVER_FUNCTIONS_SECRET_FILE 環境変数(キーファイルへのパス)
  3. ランタイム構成内のserverFunctions.secret
  4. ランタイム構成内のserverFunctions.secretFile(キーファイルへのパス)
  5. ビルド成果物 (本番ビルド時に自動生成)
  6. 一時的なランダムキー (開発時のフォールバック)
REACT_SERVER_FUNCTIONS_SECRET=my-secret-key pnpm start

またはキーファイルを指定します。

REACT_SERVER_FUNCTIONS_SECRET_FILE=./keys/action-secret.pem pnpm start
react-server.config.mjs
export default { serverFunctions: { secret: "my-secret-key", }, };

またはキーファイルを指定します。

react-server.config.mjs
export default { serverFunctions: { secretFile: "./keys/action-secret.pem", }, };

環境変数と設定値は、常にビルド成果物よりも優先されます。これにより、アプリケーションを再構築せずにシークレットをローテーションできます。

暗号化シークレットをローテーションすると、古いキーで暗号化されたトークンを含むページを開いたままのクライアントはエラーが発生します。これを回避するためにサーバーが復号時にフォールバックとして、サーバーが試行できる以前のシークレットを提供できます。

react-server.config.mjs
export default { serverFunctions: { secret: "new-secret-key", previousSecrets: ["old-secret-key"], }, };

以前のシークレット用のキーファイルも使用できます。

react-server.config.mjs
export default { serverFunctions: { secret: "new-secret-key", previousSecretFiles: ["./keys/old-secret.pem"], }, };

previousSecretspreviousSecretFilesの両方が配列を受け付けます。これらを組み合わせることで、複数の以前のキーを同時にサポートできます。

ローテーションのワークフローは以下の通りです。

  1. 現在のシークレットをpreviousSecretsに追加する
  2. secretの新しい値を設定する
  3. デプロイ — 既存のトークンはすべてフォールバック経由で引き続き機能する
  4. すべてのクライアントが更新された後(例:デプロイメントウィンドウ終了後)、previousSecretsから古いシークレットを削除する

サーバ関数の呼び出しが復号に失敗した場合(例:トークンが改ざんされた、キーがローテーションされたが以前のキーが提供されなかった、トークンが無効であるなど)、サーバーはServerFunctionNotFoundErrorをスローします。このエラーはRSCを通じてクライアントに伝播され、エラーバウンダリを使用してキャッチできます。

これによりアプリケーション内に存在するサーバ関数に関する情報が漏れるのを防ぎます。

暗号化は以下のセキュリティ特性を提供します。

暗号化はどのサーバ関数が呼び出し可能であるかを保護するものであり、それらの関数に渡される引数の内容まで妥当性を検証するわけではありません。サーバ関数の内部では、常に引数のバリデーションとサニタイズを行ってください。