Amazon API Gateway の API を Cognito で認証して呼び出す

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

API を IAM で認証する

Amazon API Gateway (以下 API Gateway) で作成した API は、誰でも呼び出せるように公開する他に、2つの認証方法が用意されています。

  • API Key をヘッダーに付与する方法 (こちらで解説)
  • IAM で認証する方法

この2つの方法のうち、今回は IAM で認証する方法を試してみたいと思います。

API Gateway にはモバイルアプリ向けの SDK を生成する機能がある点から、モバイルアプリを主なターゲットにしているように思えます。そこで、Amazon Cognito (以下 Cognito) を利用した認証方式を通して API Gateway で作成した API を呼び出してみたいと思います。

先日まで生成した SDK の認証周りでエラーが発生し Cognito (IAM Role) を利用した呼び出しが行えないことがありましたが、生成される SDK がアップデートされたため、現在は呼び出せるようになりました。

API の作成

今回は OpenWeatherMap の Weather API をラップした API を作り、この API のクライアントを作ります。API の作成手順、および SDK の生成手順は以下のブログにまとめてありますので、こちらの手順通りに作成してください。

API の Authorization type の変更

次に、作成した API の Method の Authorization type を変更します。まず Method Execution 画面を表示し、Method Request をクリックします。

gateway-iam01

Authorization type は NONE または AWS_IAM のいずれかを選択できます。今回は AWS_IAM を設定しましょう。また ARN は後で使うのでメモっておきましょう。

gateway-iam02

ここまで終わったら、デプロイを行っておきましょう。なお SDK が生成済みの場合は再度生成する必要はありません。

Cognito の Identity Pool の作成

次に Cognito の Identity Pool を作成します。Cognito の Management Console を開き「Create Identity Pool」をクリックします(Identity Pool を作成したことがない場合は「Get Started」)。

gateway-iam03

Identity pool nameAPIGatewayApp としました。また、今回は認証プロバイダを用いた認証を行いませんので、Unauthenticated identitiesEnable access to unauthenticated identities にチェックを入れておきましょう。

gateway-iam04

次に IAM Role の作成画面が表示されるので、ここで新規作成するポリシーを調整しましょう。2番目の Role SummaryView Policy Document をクリックし、続けて Edit をクリックします。

gateway-iam05

IAM Policy は、次のようにしましょう。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"           
      ],
      "Resource": [
        "arn:aws:execute-api:us-east-1:xxxxxxxxxxxx:xxxxxxxxxx/*/GET/weather"
      ]
    }
  ]
}

Action には execute-api:InvokeResource に Method Request に表示されている ARN を貼り付けましょう。

これで Identity Pool の完成です。サンプルコードの中に書かれている Identity Pool ID をメモしておいてください。

iOS アプリから呼び出す

それでは、iOS アプリを実装しましょう。ここで使う iOS アプリは以下のブログで作成したものを使います。記事を参考に、作成しておいてください。

上記の処理に加えて、Cognito の認証情報を組み込む処理が必要になります。これは以前までと全く同じ方法ですので、新しく何か必要になるわけではありません。

// Cognito認証
AWSCognitoCredentialsProvider *provider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1
                                                                                     identityPoolId:@"us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"];
AWSServiceConfiguration *configutation = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1
                                                                     credentialsProvider:provider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configutation;

CLIWeatherAPIClient *client = [CLIWeatherAPIClient defaultClient];
[[client weatherGet:@"London"] continueWithExecutor:[AWSExecutor mainThreadExecutor]
                                         withBlock:^id(AWSTask *task) {
    if (task.error) {
        NSLog(@"Error: %@", task.error);
    } else if (task.exception) {
        NSLog(@"Exception: %@", task.exception);
    } else {
        CLIWeather *weather = task.result;
        CLIWeather_weather_item *item = weather.weather.firstObject;
        NSString *message = [NSString stringWithFormat:@"Weather: %@", item.main];
        [[[UIAlertView alloc] initWithTitle:@"Get response"
                                   message:message
                                  delegate:nil
                         cancelButtonTitle:nil
                         otherButtonTitles:@"Close", nil] show];
    }
    return nil;
}];

これで、認証付きで呼び出せました。

api-gateway-ios12

Android アプリから呼び出す

今度は、Android アプリを実装しましょう。ここで使う Android アプリは以下のブログで作成したものを使います。記事を参考に、作成しておいてください。

上記の処理に加えて、Cognito の認証情報を組み込む処理が必要になります。これは以前までと全く同じ方法ですので、新しく何か必要になるわけではありません。

void invoke() {
    // Cognitoの認証
    CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
            self, // Context
            "us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // Identity Pool ID
            Regions.US_EAST_1 // Region
    );

    WeatherAPIClient client = new ApiClientFactory()
            .credentialsProvider(credentialsProvider)
            .build(WeatherAPIClient.class);
    Weather weather = client.weatherGet("Toyko");
    WeatherWeatherItem item = weather.getWeather().get(0);
    final String message = "Weather : " + item.getMain();
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            new AlertDialog.Builder(self)
                    .setTitle("Weather")
                    .setMessage(message)
                    .setPositiveButton(android.R.string.ok, null)
                    .create()
                    .show();
        }
    });
}

Android でも認証付きで呼び出せました。

gateway-android04

まとめ

API Gateway の API は IAM を使って細かく制御できます。例えば、未ログインユーザーはこの API の GET だけ、ログインユーザーは POST もできるようにするなどといったポリシーも実現可能です。モバイルアプリでも API Gateway をぜひ使っていきましょう!

参考