0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CloudFrontにCognitoとLambda@Edgeで認証機能を追加する

Posted at

個人開発レベルでBedrockを呼び出すチャットボットアプリを作成していたのですが、そのアプリに認証機能を作成したいなと思い立ったため、備忘録的にこの記事を残します。

チャットボット作成してみた件はこちらから。

ユーザプールの作成

認証のみ実施したいので、IDプールは使用しません。ユーザプールとIDプールの違いについては、以下を参照ください。

【Cognito】User PoolとIdentity Poolについて - Qiita

ユーザプールを作成していきます。

Reactで作成したSPAが、既にS3でホスティング済みのため、「シングルページアプリケーション(SPA)」を選択します。

また、「従来のウェブアプリケーション」と「シングルページアプリケーション」の違いはクライアントシークレットの有無に基づいているそうです。今回はクライアントシークレットを持たない「シングルページアプリケーション」を選択してます。

名前は任意でOKです。
1.png

サインインオプションを選択していきます。

今回は「Eメール」を使用することにします。
2.png

「リターンURL」は、CloudFrontのディストリビューションドメイン名を指定します。要はコールバックするURLのことです。

複数登録できるので、以下3つを登録してます。

アプリケーションのリソースを設定する画面に遷移しましたが、後でも設定できるので、ここではページ右下の「概要に移動」をクリックして飛ばします。
3.png

ユーザプールが完成したので、ログインページを表示してログインを試します(僕はマネジメントコンソール上で事前にユーザを作成してからログインしました)。
4.png

想定したページへとコールバックされました。
5.png

しかしながら、現段階だとCloudFrontのディストリビューションドメイン名を直接叩いてもコールバック先へとアクセスできてしまいます。

そこで、CloudFrontにアクセスするとCognitoの認証ページに遷移するように設定を追加していきます。

CloudFrontとCognitoの連携

連携には「cognito-at-edge」を使います。

このNode.jsパッケージは、CloudFrontディストリビューションへのリクエストを行うユーザーがCognitoユーザープールを使用して認証されているかどうかを確認するのに役立ちます。この確認は、リクエストに含まれるCookieを参照することで行われ、リクエスト元が認証されていない場合は、ユーザープールのログインページにリダイレクトされます。

上記URLに記載の通り、まずはパッケージのダウンロードをしていきます。

CloudShellを起動して、以下のコマンドを打ちます。

mkdir cognito-at-edge
cd  cognito-at-edge
npm install cognito-at-edge
vi index.js

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', // user pool region
  userPoolId: 'us-east-1_tyo1a1FHH', // user pool ID
  userPoolAppId: '63gcbm2jmskokurt5ku9fhejc6', // user pool app client ID
  userPoolDomain: 'domain.auth.us-east-1.amazoncognito.com', // user pool domain
});

exports.handler = async (request) => authenticator.handle(request);

ユーザプールIDは以下に記載されてます。
6.png

クライアントIDは以下に記載されてます。
7.png

ユーザプールドメイン名は以下に記載されてます。
8.png

記載が完了したら、zip化します。

zip -r9 cognito-at-edge.zip *

zipファイルをS3にアップロードしておきます。

aws s3 cp cognito-at-edge.zip s3://<S3バケット名>/cognito-at-edge.zip

Lambda@Edgeの作成

作成したパッケージをLambda@Edgeにアップロードしていきます。

注意点として、Lambda@Edgeの制限上、Lambda 関数は、米国東部 (バージニア北部) リージョンにある必要があります。

Lambda@Edge に対する制限 - Amazon CloudFront

以下のようにLambda関数を作成しました。

関数名:cognito-at-edge

ランタイム:Node.js 22.x

アーキテクチャ:x86_64

アクセス権権:AWSポリシーテンプレートから新しいロールを作成

アクセス権限については、ポリシーテンプレートの選択肢から以下を選択します。
9.png

関数が作成し終わったら、S3に格納しておいたzipファイルをLambda関数にアップロードします。
10.png

アップロードが完了しました。
11.png

続いて、画面右上の「アクション」から「Lambda@Edgeへのデプロイ」をクリックします。
12.png

ディストリビューションには、対象となるCloudFrontを選択します。
13.png

CloudFront側のステータスも有効になったらテストしてみます。

CloudFrontディストリビューションのURLを直接叩くと、Cognitoのサインイン画面にリダイレクトされました。うまくいってます。
14.png

ログイン動作も問題なかったです。

503エラー発生

ある程度時間を置いてからまたテストすると503エラーが発生してしまいました。
15.png

同じ現象が発生している記事を見つけましたので、こちらを参照します。

ユーザー認証付きの静的サイトをCognito+CloudFront+Lambda@Edgeで構築する - Qiita

え、クライアントシークレットを設定するってことは、ユーザプールのアプリケーションタイプを「従来のウェブアプリケーション」で作成し直さないといけないのか(SPAだとクライアントシークレットは無いため)。

てことで作り直しました。
16.png

ついでに以下の記事を見つけまして、バグが発生していたとな。

ということで、まとめてindex.js を編集していきます。

cognito-at-edge は CookiePath を指定して使おう

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

const authenticator = new Authenticator({
  // Replace these parameter values with those of your own environment
  region: 'us-east-1', // user pool region
  userPoolId: 'us-east-1_tyo1a1FHH', // user pool ID
  userPoolAppId: '63gcbm2jmskokurt5ku9fhejc6', // user pool app client ID
  userPoolDomain: 'domain.auth.us-east-1.amazoncognito.com', // user pool domain
  userPoolAppSecret: 'XXXXXX', // 追加
  cookiePath: '/', // 追加
});

exports.handler = async (request) => authenticator.handle(request);

上記で503エラーも解決しました。

ずっと勘違いしていたかもだけど、Cognitoの「ログインページを表示」から取得できるURLからログインすると503エラーが起きて、CloudFrontディストリビューション名/index.html をブラウザで叩くとエラーが起きないという挙動(ログインしてなかったらログインページに遷移)。

つまり、「ページにアクセスするためのURL=コールバックするURL」ということをちゃんと認識して、テストする際のURLはCloudFrontディストリビューション名/index.html を貫いていれば、503エラーがそもそも出なかったんじゃないか。それはまた別の機会に実験したいと思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?