はじめに
特定のユーザのみにAmazon API Gatewayを提供したいと思い調査したので、
そのときのメモをまとめました。
API Gatewayとは
名前の通り、APIの入り口となるようなサービスです。
API Gatewayを経由し、Lambda関数を呼び出したり別のエンドポイントにアクセスしたりできます。
デフォルトでは認証なしの状態で作成されるため、誰でもAPIアクセスが可能です。
Cognitoとは
AWSが提供する認証関連のサービスです。
3つの機能で構成されています。
Amazon Cognito ユーザープール
IdPとして働き、ユーザ情報の管理を行います。Amazon Cognito フェデレーテッドアイデンティティ
IdPと連携して新たなIDを作成し、ユーザにひもづく複数のIdPを統合して取り扱うことができます。
また、権限が制限された一時的なAWS認証情報を取得して、他のAWSサービスにアクセスが可能です。Amazon Cognito Sync
デバイスごとのデータ連携等で利用します。
今回はあまり調査をしていませんので割愛。
API Gatewayの認証方法
「メソッドリクエスト」のところにある「認証」から選択ができます。
カスタムオーソライザー
API Gatewayの設定
APIの「オーソライザー」から、「Cognitoユーザープールオーソライザー」を選択します。
適宜ユーザープールを選択し設定完了です。
そのあと、メソッドリクエストに先ほど作成したカスタムオーソライザが表示されているので、
そちらを選択してください。
呼び出し元の実装
カスタムオーソライザーのデフォルトでは、Cognito UserPoolから払い出された「IDトークン」「アクセストークン」「リフレッシュトークン」のうち、「IDトークン」をAuthorizationヘッダに付与して送信することで認証が行われます。
IAM
API Gatewayの設定
「認証」で「IAM」を選択してください。
呼び出し元の実装
こちら少し複雑ですが、
- Cognito ユーザープールから「IDトークン」「アクセストークン」「リフレッシュトークン」を取得
- Cognito フェデレーテッドアイデンティティに「IDトークン」を送付
- Cognito フェデレーテッドアイデンティティが内部でSTSと通信し、一時的な認証情報を取得しクライアントへ
- クライアントは、フェデレーテッドアイデンティティから受け取った「アクセスキーID」「セキュリティキー」「セッショントークン」をもとに署名を行う
- 署名された文字列をAuthorizationヘッダまたはクエリ文字列に付与して送信する
といった流れになります。
署名関連については、署名バージョン4を使用してAWSリクエストに署名するを確認ください。
署名の実装についてですが、JavaScriptであればaws4等を利用すると楽かと思います。
カスタムオーソライザーとIAMの比較
認証方法 | 認証に必要な情報 | 設定方法 | 利用するサービス | 補足 |
---|---|---|---|---|
カスタムオーソライザー | UserPoolから取得した「IDトークン」 | IDトークンをヘッダに設定 | Cognito UserPool | API Gatewayのみで利用可能 |
IAM | STSから取得した「アクセスキーID」「セキュリティキー」「セッショントークン」 | 署名した文字列をヘッダまたはクエリ文字列に設定 | Cognito UserPool/Cognito Federated Identity/STS | API Gateway以外のサービスでも利用可能(S3での認証等) |
ポイントとなるのは「設定方法」の項目で、カスタムオーソライザーではヘッダのみの設定となっています。
あまりないとは思いますが、ヘッダが設定できない場合はIAMの認証でクエリ文字列を設定するほうがよいかと思います。
(S3でクエリ文字列認証をつけた場合、x-amz-expiresで有効期限をある程度設定できるのですが、クエリ文字列でのAPI Gateway認証は5分程度しか有効ではないようです。サポートに聞いてみましたが、x-amz-expiresはAPI Gatewayでは有効にならないとのことでした。)
参考情報
CognitoとAngular2を使ったサンプル。
API Gatewayの処理はないのですが、STSからキーを取得する処理や、IDトークンを取得するソースがあったので
こちらのソースを触りながら勉強しました。
https://github.com/awslabs/aws-cognito-angular2-quickstart
IAMで認証をかける記事です。
Cognito以外の設定も記載がありとても勉強になるので、Cognitoを利用する方にはぜひ読んで欲しいです。
世界に先駆けてAWSサーバレスアーキテクチャでユーザ認証とAPI認可の実装をしてみた
TODO
- 認証方法のところに図の追加
- Cognito UserPoolから各種トークンを取得するための実装
- Cognito Federated IdentityとUserPoolの連携、STSからのキー/トークンの取得するための実装
- Cognito Federated IdentityのIAMの設定