Cognitoの認証を使用して、APIGatewayの使用を制限する

1.はじめに

今回はかなり初歩的な内容とはなりますが、Cognitoを使用したAPIGatewayの制限を実施していきます。

扱う内容はCognitoによる制限に焦点を当てたものですので、APIの実装に関しては以下「AWS Hands-on for Beginers」の内容のものを利用します。

参照:サーバーレスアーキテクチャで翻訳Wrb APIを構築する
pages.awscloud.com

構成は以下のようになります。

2.使用するサービス

Amazon APIGateway
 APIの実装・管理を容易にしてくれるサービスです。
aws.amazon.com

Amazon Translate
 テキストの翻訳を行えるサービスです。
aws.amazon.com

Amazon Cognito
 ユーザーの管理やアクセス制限が行えるサービスです。
aws.amazon.com

3.環境の構築

まずはハンズオンで実施している内容をかいつまみながら、今回実施する環境の構築を行います。

▼ここからハンズオンの内容


LambdaとAmazon Translateを使用して、日本語を英語に翻訳するアプリケーションを作成します。

まずはLambdaでpythonを使用した関数の作成を行います。
今回は記事作成時点で最新のpython3.12を使用しています。

 コードは以下の内容となります。

import json
import boto3

translate = boto3.client('translate')

def lambda_handler(event, context):

    input_text = event['queryStringParameters']['input_text']

    response = translate.translate_text(
        Text=input_text,
        SourceLanguageCode='ja',
        TargetLanguageCode='en'
    )

    output_text = response.get('TranslatedText')

    return {
        'statusCode': 200,
        'body': json.dumps({
            'output_text': output_text
        }),
        'isBase64Encoded': False,
        'headers': {}
    }

※コードの内容などが気になる方はAWSハンズオンをご参照ください。
 わかりやすく説明されており、おススメです。

Lambdaのロールに「TranslateReadOnly」をアタッチします。
(ハンズオンでは「TranslateFullAccess」を使用していますが、そこまでの権限は不要ですのでこちらの権限に変更しています。)


①で作成したLambdaを使用してAPIGatewayを作成します。

以下の内容でAPIGatewayを作成します。
APIタイプ:REST API
・メソッドタイプ:GET
・統合タイプ:Lambda関数 「Lambdaプロキシ統合」にチェック
・Lambda関数:①で作成したLambda関数

「translate」というリソース名を作成して、ステージ名「api」でデプロイします。
ステージの「GET」に記載されているURLをコピーしてブラウザで確認すると、以下のエラーが表示されます。

このエラーは翻訳したい内容の記載をしていないため出ています。

クエリストリングを記載して再度アクセスすると、無事翻訳されていることが確認できます。

▲ここまでがハンズオンの内容

 ※実際のハンズオンではこの後にRDSへの記録もあるのですが、今回の内容では関連しないため省きます。

4.Cognitoによる制限

こちらの翻訳機能を提供しているAPIGatewayを、認証済みのユーザーだけが利用できるようにCognitoで制限をかけていきます。

まずコンソールでCognitoを開き、「ユーザープール」の「ユーザープールを作成」を選択します。

以下の設定内容を使用して、その他の設定に関しては適宜選択してください。

・多要素認証:MFAなし
・ホストされた認証ページ:チェック
ドメイン:Cognitoドメインを使用する
・許可されているコールバックURL:https://localhost

ユーザープールが作成されたら、まず「ユーザーを作成」を選択してユーザーを作成します。

この時点でユーザーは作成されましたが、まだ初回ログインとパスワードの変更が行われていない状態です。

「アプリケーションの統合」から「アプリクライアントと分析」にある、アプリケーションクライアントを選択します。

「ホストされたUI」の「ホストされたUIを表示」を選択すると、Cognitoが提供するログイン画面が表示されます。

ここで先ほど作成したユーザーで初回ログインとパスワード変更を行います。

パスワード変更を実施すると、ユーザープール作成時に「許可されているコールバック」として設定した先にリダイレクトされます。
今回はlocalhostとしたので、接続エラーとなります。

Cognito の設定はここまでとなります。

5.APIGateway設定

APIGatewayでCognitoの認証を使用する設定を行います。

APIGatewayの「オーソライザー」から「オーソライザーを作成」を選択します。
「オーソライザーのタイプ」は「Cognito」、「Cognitoユーザープール」で先ほど作成したユーザープールを選択します。

認証成功後はヘッダーの「Authorization」に認可トークンを格納するので、「トークンのソース」に「Authorization」と記載をして「オーソライザーを作成」を実行します。

トークンの値」に何も入れずに「オーソライザーをテスト」を実施すると401が返ってきて、「Unauthorization」が表示されます。

認証されたユーザーの認可トークンを確認する方法はいくつかありますが、AWSCLIで以下のコマンドを入力することでCognitoへの認証を実施してレスポンスを確認することができます。

$ aws cognito-idp admin-initiate-auth --user-pool-id [ユーザープールID] --client-id [アプリケーションクライアントのクライアントID] --auth-flow ADMIN_NO_SRP_AUTH --auth-parameters USERNAME=[ユーザー名],PASSWORD=[パスワード]

ただ、こちらの認証を行うためには「アプリケーションクライアント」で「認証フロー」に「ALLOW_ADMIN_USER_PASSWORD_AUTH」を追加する必要があります。

上記の追加が完了後、コマンドを実行します。

すると以下のような形でいくつかのパラメーターが返されます。

{
  "ChallengeParameters": {},
  "AuthenticationResult": {
    "AccessToken": "[Base64でエンコードされたアクセストークン]",
    "ExpiresIn": 3600,
    "TokenType": "Bearer",
    "RefreshToken": "[Base64でエンコードされた更新トークン]",
    "IdToken": "[Base64でエンコードされたIDトークン]",
  }
}


トークンの詳細は以下のページを参照ください。
docs.aws.amazon.com

このうちの「IdToken」の値をコピーして先ほどのAPIGatewayの「トークンの値」に入力後、再度「オーソライザーのテスト」を実施します。

すると次は成功して、StatusCode:200と各値が返ってきます。

これでCognitoが正常にオーソライザーとして設定できていることを確認できました。

次にこのオーソライザーをAPIGatewayに設定します。
APIGatewayの「リソース」からメソッドの「GET」を編集して、「認可」に先ほど設定したオーソライザーを選択して保存します。

APIをデプロイ」を実行することで、Cognitoの認証がアタッチされたAPGatewayがデプロイされます。

6.動作確認

確認のためにAPIへのリスエストを実行すると「Unauthorized」と表示され、APIGatewayに認証の機能がひもづいたことを確認できました。

認証されたユーザーであれば使用できるかの確認は、Postmanなどのアプリを使用すると簡単に行えます。

www.postman.com (今回の内容ですとブラウザ版だけで確認できます。)

Postman上でURL、ヘッダーに「Authorization」キー、値にオーソライザーのテスト時に使用した「トークンの値」を入力して送信を実行します。

レスポンスが返ってきて、下部の欄に翻訳された文章が返ってきていれば成功です。


今回の内容は以上となります。

7.まとめ

今回の内容はユーザープールのデフォルトのログイン画面や認証によるAPI使用制限の確認だけと、初歩的な内容の記事となりました。

実際のアプリケーションとしての使用やIDプールによるリソースの制限など、Cognitoでよく利用される内容に関しても機会があれば記事をかければと思います。

この記事が多少でも役に立っていただければ幸いです。