ユーザー認証
概要
プライベートコンテンツを公開する Web アプリケーションには、許可されたユーザーのみがコンテンツにアクセスできるようにするためのアクセス制御メカニズムが必要です。例としては、ユーザー認証を必要とするSPAベースの内部ポータルや、機密ファイルのダウンロードなどがあります。アクセス制御は、ユースケースに応じて、オリジンレベルまたはCDNレベルで実装できます。
一般的ユースケース
オリジンベースの認証
CloudFront をキャッシュを有効にせずにリバースプロキシとして使用している場合 (つまり、マネージドキャッシュポリシーで Caching Disabled が設定されているなど)、オリジンのネイティブ認証機能 (API Gateway など) を簡単に使用できます。これを正しく機能させるには、 Authorizationヘッダーなどの認証情報を含むリクエスト属性をオリジンに転送するようにオリジンリクエストポリシーを設定します。
コンテンツはキャッシュ可能だが、独自のインフラストラクチャで引き続き認証を管理したい場合は、Lambda @Edge を使用して CloudFront を認証サーバーと統合することを検討してください。このアーキテクチャにより、CloudFront キャッシュの恩恵を受けることができます。この実装の詳細については、このブログをご覧ください。
認証ロジックをウェブアプリケーションコンポーネントから CloudFront にオフロードする場合は、以下のセクションを検討してください。
署名付きトークンを使用した CloudFront ベースの認証
CloudFront は、署名付き URL または署名付き Cookie を使用するネイティブ認証メカニズムを提供します。この方法を使用するには、ドキュメントで説明されている手順に従ってください:
- 署名キーグループを使用して、署名トークン用の非対称暗号キーを設定します。
- 認証ワークフローで、ベンダーリソース URL のクエリパラメータまたは Cookie に必須のトークンフィールドを追加します。トークンには、有効期限、署名キー ID、ポリシー、および署名が含まれます。このポリシーでは、CloudFront によるトークン検証テストに合格するためにリクエストが満たす必要がある条件を定義できます。たとえば、カスタムポリシーを使用して、特定のパスで始まるすべての URL に有効なトークンを生成できます。
- プライベートコンテンツに使用される CloudFront のキャッシュ動作で署名を有効にします。それ以降は、すべてのリクエストが CloudFront によって制御され、トークン検証が行われます。許可されていないリクエストには 403 エラーが送信されます。このエラーは、CloudFront のカスタムエラーページ機能を使用してカスタマイズできます。
aws-sdk を使用して、プライベートキーを含む有効なトークンを生成します。例として、Nodejs の以下のコードは、2 時間有効な edge-image.jpg という特定のオブジェクトの CloudFront 署名付き URL を生成します。
const AWS = require('aws-sdk');
// It's recommended not to store signing keys in code. The below is just an illustrative example.
const cloudfrontAccessKeyId = 'K25ULYFPSTHQP9';
const cloudFrontPrivateKey = '-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQ....2gvvIH\n-----END RSA PRIVATE KEY-----';
const signer = new AWS.CloudFront.Signer(cloudfrontAccessKeyId, cloudFrontPrivateKey);
const signedUrl = signer.getSignedUrl({
url: 'https://d3jqlnxofenq2x.cloudfront.net/edge-image.jpg',
expires: Math.floor((Date.now() + 2 * 60 * 60 * 1000) / 1000),
});
console.log(signedUrl);
上記のコードスニペットの出力は次のようになります:
https://d3jqlnxofenq2x.cloudfront.net/edge-image.jpg?Expires=1660317158&Key-Pair-Id=K25ULYFP9THQP9&Signature=agW2XF9S5AW0YCc6c7pkCwccJmxaIAWFO~uXn9KtOXtz4JTY7eRF07opJiseGXJxzlMeD4V6FUH8I-gOH~Gvafa16RFV9IryxCyzL9mIYt-XbDKMrY0ONzTWUk2x16AKDK27VoUwEPiI9dpPXMp7f4MsrpKA-u6huZCsulh0~aAYN~x25uNoDO-WgZpfkKFeKc910u4PVnEaKLlZlpuJ0hqWUjMVPes9DfA~msToJeyjrVzLi2R8O8LuuYHsAMAHXr7E9qB8tAoDWz24CurCirxc6sB45Zc-oK9JigX0L4~F~F1TE9i39ysmQF4UrOyu0bp7MKGSDBwLE1P2C3gWNw__
CloudFront Functions を使用したクラウドフロントベースの認証
CloudFront のネイティブ署名付きトークンが認証要件を満たさない場合は、エッジ関数を使用してカスタム認証ロジックを構築できます。たとえば、対称暗号など、トークンの署名に別の暗号方式を使用したり、ユーザーエージェントヘッダーなどの非標準属性を署名に含めたり、ユーザーネットワークに基づいて条件付きトークン化ロジックを実装したりしたい場合があります。以下のカスタム実装は、エッジ関数の可能性の一部を示しています:
- JWT ベースのトークンを検証するための CloudFront 関数。CloudFront Functions は現在、外部ネットワーク呼び出しを許可していないため、署名キーを関数コードに保存する必要があることに注意してください。署名キーを CloudFront 関数コードに保存するリスクを軽減するには、コードでキーを手動で設定するのではなく、CloudFront にデプロイする前にキーをローテーションして関数コードを生成する自動化を使用してください。この方法では、キーが Github などのパブリックリポジトリにアップロードされるリスクがありません。
- AWS ソリューション:エッジでの安全なメディア配信。この AWS ソリューションでは、CloudFront Function を使用して、動画ストリーミングに合わせたカスタム認証メカニズムを実装しています。
- OpenID Connect を使用して S3 でホストされているシングルページアプリケーションを認証します。このソリューションでは、AWS Secrets Manager を使用して署名キーを保存し、Cognito や Okta などの外部アイデンティティプロバイダー (IdP) と連携できます。この実装は CloudFront Functions のリリース前に公開されたため、完全に Lambda @Edge に依存しています。認証部分には CloudFront 関数を使用し、IdP との統合には Lambda @Edge を使用するように最適化できます。