概要
- CloudFrontでCognito認証したい場合は、Lambda@Edgeを使ってcognito-at-edgeを扱った記事は多い。
- 一方、CloudFrontでファイル名を含まないURLをリクエストした際にindex.htmlを追加する方法としてはCloudFront Functionsを使ったサンプルの記事が多い。(公式でも記載されている)
- 問題点はcognito-at-edgeと同時に使いたい場合にビューワーリクエストで指定することになるため、どちらか片方しか設定できないこと。
- オリジンリクエストでCloudFront Functionsは指定できない。
- オリジンリクエストでLambda@Edgeは可能だが、認証系がキャッシュされてしまう?未確認だが期待する動きをしないと思われる。
- この記事では、どちらの機能も実装したLambda@Edge関数を作成し解決方法を紹介する。
- なお、Lambda@EdgeやCloudFront、Cognitoの基本的な設定方法については割愛する。
結論
- 以下のようにLambda@Edge関数を作成して、ビューワーリクエストで指定すれば実現できる。
const { Authenticator } = require('cognito-at-edge')
const authenticator = new Authenticator({
region: <<region>>,
userPoolId: <<pool_id>>,
userPoolAppId: <<app_id>>,
userPoolDomain: <<pool_domain>>,
})
export const handler = async (event) => {
const result = await authenticator.handle(event)
if ('status' in result) {
return result
}
var uri = result.uri
if (uri.endsWith('/')) {
uri += 'index.html'
}
else if (!uri.includes('.')) {
uri += '/index.html'
}
result.uri = uri
return result
}
解説
- まず、cognito-at-edgeの認証処理を行うために、
Authenticator
をインスタンス化する。 - その後、
Authenticator
のhandle
メソッドを呼び出すことで、認証処理を行う。 -
handle
メソッドの戻り値は、認証成功時はリクエストオブジェクトを、失敗時は画面遷移のステータスコードを持ったレスポンスオブジェクトを返す。 - そのため、戻り値に
status
プロパティがあるかどうかで、認証成功かどうかを判定できる。 - そのあとは、リクエストオブジェクトの
uri
プロパティを参照し、/
で終わっている場合はindex.html
を追加し、拡張子がない場合は/index.html
を追加する。
今後の検討課題
- ユーザ単位にページの参照可否を制御したいと思った場合に、上記Lambda@Edge関数に機能を実装する必要があるが、cognito-at-edgeは認証情報までは返してくれない。
- cognito-at-edgeに要望を出すか、必要な機能を移植するか。(それなりにプロジェクト自体は活動されているようだが、放置されているプルリクが気になる。)