メモ

ACTABAのホームページ

TOP > AWS S3のWEBサイトをCognitoでユーザ認証してみた

見出し

AWS S3で公開しているWEBサイトを一部のユーザに公開したいことはよくあります。
ここでは、AWS Cognitoを使用して認証済みのユーザだけがWEBサイトを参照できるようにしてみたのでそのメモ。(2022/10)
参考にしたサイトは下記
https://github.com/awslabs/cognito-at-edge
https://github.com/aws-samples/cloudfront-authorization-at-edge
https://aws.amazon.com/jp/blogs/news/signed-cookie-based-authentication-with-amazon-cloudfront-and-aws-lambdaedge-part-2-authorization/
https://aws.amazon.com/jp/blogs/networking-and-content-delivery/authorizationedge-using-cookies-protect-your-amazon-cloudfront-content-from-being-downloaded-by-unauthenticated-users/?nc1=h_ls

S3でWEBサイトを公開する

S3で公開するWEBサイトを作成します。
ユーザ認証は後から追加しますので、このセクションではS3とCloudFrontを使用してWEBサイトの作成をします。

S3にWEBサイト用のバケットを作成する

AWSコンソールでS3を表示します。
1. 「バケットを作成」をクリックします。
S3バケットの作成

2. バケット名を入力します。ここでは「homepage-my-ac」とします。画面右下の「バケットを作成」をクリックします。
S3バケットの作成
S3バケットの作成

CloudFrontでWEBサイトを公開する

AWSコンソールでCloudFrontを表示します。
1.「ディストリビューションを作成」をクリックします。
CloudFrontでWEBサイトを公開する

2. WEBサイトとして公開するS3バケットを選択します。「オリジンドメイン」をクリックして「Amazon S3」セクション内の先ほど作成したバケット「homepage-my-ac」から始まるドメインを選択します。
CloudFrontでWEBサイトを公開する

3.「S3バケットアクセス」は「Origin access control settings (recommended)」を選択します。
新しくバケットポリシを作成するので「Origin access control」の右の「コントロール設定の作成」をクリックします。
CloudFrontでWEBサイトを公開する

4.「Create control setting」画面が表示されますので、「作成」をクリックします。
5.「Origin access control settings (recommended)」のリストから作成したバケットポリシを選択します。
CloudFrontでWEBサイトを公開する

6. 画面右下の「ディストリビューションを作成」をクリックします。
CloudFrontでWEBサイトを公開する

s3に登録するhtmlファイルは下記のシンプルなhtmlファイル。
サンプルhtml

これでS3のバケットをWEBサイトとして公開できました。
次に、WEBサイトにアクセスしたときにユーザ認証していないときはログイン画面を表示してユーザ認証をするようにします。

WEBサイトにユーザ認証の機能を追加する

ユーザ認証にAWS Cognitoを使用します。
はじめにCognitoを構成します。

AWS Cognitoを構成する

1. AWSコンソールでCognitoを表示します。
2.「ユーザープールを作成」をクリックします。
AWS Cognitoを構成する

3.「サインインエクスペリエンスを設定」画面が表示されます。下記を設定します。
  Cognito ユーザープールのサインインオプション:「ユーザー名」をチェックする。
   (今回はユーザー名でログインするようにしてみます)
  ユーザー名の要件:「ユーザーが任意のユーザー名でサインインすることを許可」をチェックする。
AWS Cognitoを構成する

4. 画面下の「次へ」をクリックします。
5.「セキュリティ要件を設定」画面が表示されます。下記を設定します。
  多要素認証:オプションのMFA
  Authenticator アプリケーション:チェックする。
   (今回はAuthenticator アプリケーションのみにチェックします。)
AWS Cognitoを構成する

AWS Cognitoを構成する

6.「次へ」をクリックします。
7.「サインアップエクスペリエンスを設定」画面が表示されます。下記を設定します。
  自己登録を有効化:チェックを外す。
   (今回はあらかじめ登録したユーザがサインインできるようにしてみます。)
AWS Cognitoを構成する

8. 画面下の「次へ」をクリックします。
9.「メッセージ配信を設定」画面が表示されます。下記を設定します。
  Eメールプロバイダー:Cognito で E メールを送信
   (今回はテスト目的なのでSMSは使用しないでメールしてみます)
AWS Cognitoを構成する

10. 画面下の「次へ」をクリックします。
11.「アプリケーションを統合」画面が表示されます。下記を設定します。
  ユーザープール名:my-app-s3-test
  Cognito ドメイン:my-app-s3-test-nvj16g5u
   (任意の文字列を指定します)
  「Cognito のホストされた UI を使用」:チェックする
   (ここでは、サインイン画面はデフォルトの画面を使用してみます。)
  アプリケーションクライアント名:my-app-s3-test-public-client
  許可されているコールバック URL:https://d1g2265jecwyam.cloudfront.net
  許可されているサインアウト URL:https://d1g2265jecwyam.cloudfront.net
   (「cognito-at-edge」はドメイン名までのURLにコールバックするようなので、ドメイン名までを入力します)。
AWS Cognitoを構成する

AWS Cognitoを構成する

AWS Cognitoを構成する

AWS Cognitoを構成する

12. 画面下の「次へ」をクリックします。
13.「確認および作成」が表示されます。画面下の「ユーザープールを作成」をクリックします。
AWS Cognitoを構成する

以上でCognitoの構成は終了です。

ユーザ認証のためのLamba関数を作成する

CloudFrontでユーザ認証するには、ディストリビューションのビューワーリクエストにLambda@Edge関数を設定します。
これにより、CloudFrontで受けたアクセス要求をLambda@Edge関数でユーザ認証を検証し、OKであればS3のコンテンツを返し、NGの場合は認証画面を表示することができます。

Lambda関数を作成します。
AWSからcognito-at-edgeというライブラリが提供されていますので今回はそれを使用します。
参考:https://github.com/awslabs/cognito-at-edge

AWS Lambdaに登録する関数を準備する

cognito-at-edgのライブラリはnpmでダウンロードします。
Windowsの場合は、https://nodejs.org/からnodejsをダウンロードしてインストールします。
nodejsにnpmも含まれています。
コマンドプロンプトを起動して、フォルダ「cognito-at-edge」を作成し、カレントフォルダにします。
下記のコマンドを実行します。パッケージ一式がカレントフォルダにダウンロードされます。

npm install cognito-at-edge

フォルダ「cognito-at-edge」にファイル「index.js」を作成します。 下記のコードを記載します。

const { Authenticator } = require('cognito-at-edge');

const authenticator = new Authenticator({
	// Replace these parameter values with those of your own environment
	region: 'us-east-1',
	userPoolId: 'us-east-1_r0Vxxxxxx',
	userPoolAppId: '5soad8xxxxxxxxxxxxxxxxxxxx',
	userPoolDomain: 'my-app-s3-test-nvj16g5u.auth.us-east-1.amazoncognito.com',
});

exports.handler = async (request) => authenticator.handle(request);
※userPoolId、userPoolAppId、userPoolDomainの値は、Amazon Cognitoのユーザープールの下記の値です。
 userPoolId:「ユーザープール ID」
 userPoolAppId:「アプリケーションの統合」タブ内の「アプリケーションクライアントのリスト」の「クライアント ID」
 userPoolDomain:「アプリケーションの統合」タブ内の「Cognito ドメイン」

フォルダ「cognito-at-edge」内のフォルダとファイルをすべて選択して、zipファイルにします。
(フォルダ「cognito-at-edge」を選択してzipファイルにするとLambda関数の実行で失敗します)

CloudFrontをユーザ認証のためのLambdaを呼び出すように構成する

CloudFrontのディストリビューションのビューワーリクエストにLambda@Edge関数を設定します。
1.CloudFrontの管理コンソールで作成したディストリビューション「homepage-my-ac」を表示します。
2.ディストリビューションのビヘイビアタブを選択します。
3.パス「/ra/」配下でユーザ認証するようにしますので「ビヘイビアを作成」を選択します。
4.パスパターン「/ra/*」を入力します。
5.作成をクリックしてビヘイビアを作成します。

AWS Lambdaに関数を登録する

作成したzipファイルをAWS Lambdaに登録します。
1.AWS LambdaのWEBコンソールを表示します。
2.Lambda@Edgeで使用するLambda関数のリージョンは「バージニア北部」にする必要がりますので、リージョンは「バージニア北部」にします。
3.Lambda関数を作成します。
  関数名:fn-vr-my-app-s3-test
  ランタイム:Node.js 16.x
4.「アップロード元」で「.zipファイル」を選択して、作成したzipファイルをアップロードします。
5.作成したlambda関数がlambda@edge関数として実行するための権限を追加します。
  「設定」タブの「アクセス権限」を選択し、「実行ロール」の右の「編集」をクリックします。
6.基本設定を編集画面が表示されます。
  「AWS ポリシーテンプレートから新しいロールを作成」をクリックします。
7.ロール名に適当な名前を入力します。
8.ポリシーテンプレートで「基本的な Lambda@Edge のアクセス権限」を選択します。 9.「保存」をクリックします。

次に、バージョンを発行して、CloudFrontに紐づけます。
1.関数の概要の「トリガーの追加」をクリックします。「トリガーを追加」画面が表示されます。
2.ソースで「CloudFront」を選択します。
3.「Deploy to Lambda@Edge」をクリックします。「Lambda@Edge へのデプロイ」画面が表示されます。
4.「Configure new CloudFront trigger」を選択。
5.「Distribution」で作成したCloufFrontのディストリビューション「d1g2265jecwyam.cloudfront.net」を選択します。
6.「Cache behavior」で「/ra/*」を選択。
7.「CloudFront event」で「Viewer request」を選択。
8.「Confirm deploy to Lambda@Edge」にチェックを付けます。
9.「デプロイ」をクリックします。
  新しいバージョンのLambda関数が発行され、デプロイされます。

動かしてみる

ユーザー認証が不要なページはそのまま表示できます。
  https://d1g2265jecwyam.cloudfront.net/index.html
ページ内の「view page」をクリックします。
ユーザー認証が必要なページなので、Cognitoのサインイン画面が表示されます。
ログインすると、
  https://d1g2265jecwyam.cloudfront.net/ra/contents.html
が表示される、、、と思っていましたが、表示されない。。。

Lambdaのログを見てみると、cognito認証後にcookieが設定されていないため、/ra/*フォルダへのアクセスが失敗していることが判明。
cognito-at-edgeのみでは実現できない様子。



Cookieを使用した認証(動くサンプル)

認証情報をCookieに保存できないかを調べたところ、「Authorization@Edge using cookies」のサンプルがあった。
環境を「AWS Serverless Application Repository」から数クリックで作成できるので、これを試してみる。
 参考:https://aws.amazon.com/jp/blogs/networking-and-content-delivery/authorizationedge-using-cookies-protect-your-amazon-cloudfront-content-from-being-downloaded-by-unauthenticated-users/?nc1=h_ls

ユーザの作成を環境作成時にできる、との記載があるがうまくいかなかった。
ユーザは作成されたが初期パスワードからの変更が必須となっていた。初期パスワードの変更ができずログインできなかった。
cognitoの管理画面にて新しいユーザを作成したところ、うまくいった。
この環境をベースに学習しよう。

AWSのサンプルの紹介となってしまった。。。


これで、AWS S3のWEBサイトをcognitoでユーザ認証してみた、は終了。


ページのトップへ戻る