こんにちは、広野です。
これまでいろいろと React アプリを AWS リソースと連携させるための仕組みをブログ記事にしてきましたが、絶対に使うであろうユースケースを書いていませんでした。以下、順を追って説明したいと思います。
本記事はアーキテクチャ編です。今後、環境編、UI 編を続編記事として用意します。
背景
こんな状況、ありませんか?
- アプリにログイン認証はある。(今回は Amazon Cognito 使用)
- アプリの動的コンテンツ (UI 画面) は AWS Amplify や Amazon S3 で配信されている。
- 静的コンテンツは Amazon S3 にあり、アプリのログイン済みユーザーにのみ閲覧を許可したい。ただし、全てのコンテンツが認証が必要なわけではなく、パブリックに公開してよいファイルもある。
- セキュリティやレスポンスを考慮し、Amazon S3 には Amazon CloudFront をかぶせてアクセスさせたい。
この状況ですと、以下に紹介するアーキテクチャが有用であると考えます。
アーキテクチャ
ざっくり全体像は以下になります。Amazon CloudFront に AWS Lambda@Edge 関数を実装することになります。
本記事では、動的コンテンツ置き場の Amplify Hosting や Amazon Cognito については基本言及せず、図の上半分の Amazon CloudFront、AWS Lambda@Edge 関数、および React コードにフォーカスします。
React アプリにログインをすると、Amazon Cognito ユーザープールからトークンをもらえます。アプリから Amazon S3 にある静的コンテンツへのリクエストを行うときにトークンを含め、間に存在する Amazon CloudFront 上で Lambda@Edge 関数によりトークンの正当性をチェックさせるという仕組みです。
以下の AWS 公式ドキュメントやブログ記事のように React アプリログイン機能を AWS Amplify で作成し、その状態になっていることが前提です。
アーキテクチャ図の上半分に少し入り込んで説明します。
- 静的コンテンツへのリクエストを行うとき、そのリクエストの Authorization ヘッダーにトークンを含めます。この動きは一般的にはデフォルトでは実施してくれないので、アプリ側で作り込む必要があります。UI 編の記事で説明します。
- リクエストは Amazon CloudFront が受け取ります。リクエストをそのまま Amazon S3 に流すのではなく、Lambda@Edge 関数でインターセプトします。
- Lambda@Edge 関数は以下の処理をします。
- リクエストが CORS プリフライトチェック (OPTIONS メソッド) であれば S3 静的コンテンツにアクセス不要なので、CloudFront に 204 No Content のレスポンスを戻すと、CloudFront がアプリに戻してくれます。このとき、CORS で必要なレスポンスヘッダー Access-Control-Allow-Origin が必要ですが、Amazon CloudFront でレスポンスヘッダーをオーバーライドする設定にしておけば Lambda@Edge 関数側で何もすることはありません。
- パブリックに公開可能 (認証不要) な静的コンテンツ (例えば public という名前のフォルダ内にあるとします) へのアクセスであれば、トークンのチェックはせずにそのまま Amazon S3 にリクエストを流します。以降、Amazon S3 からのレスポンスが Amazon CloudFront 経由でアプリに戻ります。
- その他のリクエストはトークンのチェックが必要です。Authorization ヘッダーにあるトークンの正当性を Lambda@Edge 関数内でチェックし、正当であれば Amazon S3 にリクエストを流します。不正であった場合は Amazon CloudFront に 403 Forbidden のレスポンスを戻すと、CloudFront がアプリにそれを戻してくれます。
ざっくり恐縮ですがこの方式で Amazon S3 へのアクセスを Amazon Cognito ユーザーのみに制限をかけることができます。
これを実装することによるアプリへのレスポンス影響が心配だったのですが、体感的には許容範囲でした。
続編記事


まとめ
いかがでしたでしょうか?
まだアーキテクチャ編は概要レベルなので、こんな構成で動くよね、という理解をしていただければと思います。具体的な実装面ではハマりどころがあったので、注意点として続編記事で紹介します。
本記事が皆様のお役に立てれば幸いです。



