Amazon Cognitoについてまとめてみた

## はじめに
データベースを利用したシステムにはほぼ実装されている認証・認可。その認証・認可についてインフラにAWSを採用しているシステムなら導入するにあたって一考する価値のあるAmazon Cognitoについてメリットや仕組みについて調査した記事となります。
概要レベルの内容のためコードベースでの解説は記載しておりません。（実際に書いている時間がなく...）

## Amazon Cognitoとは
https://aws.amazon.com/jp/cognito/

- システムに対して、認証、ID/PW管理・シングルサインオン・アクセス制御などをクラウド経由で提供するIDaaS(identity as a service)に分類される。Onelogin、Okta、Firebase Authentication、Auth0などが有名どころ。
- 読み方は「コグニート」。incognito（匿名の）という英単語の反対の意味を持たせた造語という説が有力のようです。

## IDaaSとは
以下の機能を有しているサービスのことのようです。
- 認証・SSO
    - ユーザーの認証
    - 多要素認証
- ID管理
    - IDaaS自身のID管理
    - 連携クラウドサービスのID管理
- ID連携
    - 連携クラウドサービスとのID連携
    - オンプレミスID基盤とのID連携
- 認可
    - サービスへの適切なアクセス権の付与
    - 条件によるサービスへのアクセスコントロール
- 監査
    - IDaaS・サービスへの認証・作業のログ取得

:::note
モバイルデバイスからの社内アセットへアクセス増加、パスワードの盗難リスク、管理負荷の上昇などに対しての適切な対処や、グローバル化による社内、社外IDを区別しないシームレスな管理に対してIDaaSが普及してきたのも頷けます。
何せ今までは一定の知識を持つエンジニアがいないと踏み込めない領域だったかと思うので。
:::


## Amazon Cognitoの特徴
前提としてIDaaSとしての機能特徴は満たされていて、そもそもその複雑な認証機能がUI設定及びローコードな実装でサービスに機能追加できるだけでも十分だと思っています。
その上で私が思うCognitoの特徴についてご紹介できればと思います。

### AWSリソースとの連携
https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-scenarios.html#scenario-aws-and-user-pool

やっぱりこれが一番強いのではないでしょうか。
いろいろこねくり回せば他社サービスでも可能かと思いますが、Cognitoの方が親和性が高く圧倒的に連携が楽かと思います。
（例えば認証済みアクセスユーザに対してS3の特定画像の閲覧を可能とする...etc）

### AWS Amplifyによる強力なサポート
https://aws.amazon.com/jp/amplify/authentication/?nc=sn&loc=3&dn=1

もはやAmplifyが優秀なのではないかと錯覚してしまいますが、その恩恵を授かることのできるCognitoが優秀ということで。Amplifyjsで認証処理、画面UIをかなり簡単に作ることをサポートしてくれています。SPAで新規サービス作るときはとりあえずこれで実装してみるのも良いかもですね。
またGraphQLを使った通信ならエンドポイント別の認証・認可もCognito+Amplify ＋ AppSyncを使えば簡単に制御できます。

### Hosted UI
https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-integration.html
サインイン、サインアップ等の画面すら作りたくない開発者も多いかと思います。そんな方用にCognitoは各ホストされている画面を提供してくれます。ID/PW以外にもGoogleログインなどのSSOにも対応しています。
ただし、日本語対応できなかったり等カスタマイズ性が低いので慎重な選択が必要そうです。

## 理解しておきたい２つのコンポーネント
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/what-is-amazon-cognito.html

実装する際は以下を理解しておくと良いかと思います。

主なコンポーネントとして
- ユーザープール
    - Webアプリやモバイルアプリのユーザーに対し、サインイン画面を含む認証機能を提供する
    - 認証完了後は「トークン」を発行し返却する
- IDプール
    - AWSの他のサービスに対するアクセスをユーザーに許可する
 

があります。それぞれは別々に使用することも可能です。


### シナリオ１.ユーザープールを使用してサーバー側のリソースにアクセスする
もっともシンプルな認証かと思います。
1.　ユーザープールにユーザーの認証情報を渡す
2.　認証情報が正しければトークンを返却する
3.　サーバー側のリソースのアクセス制御にこのトークンを使用する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737072/630496eb-9dce-7b75-7d7a-f506bcd0f0ec.png)

### シナリオ2.ユーザープールとオーソライザーを使用してエンドポイントのリソースにアクセスする
API Gatewayを使っているREST APIシステムならとAmazon Cognitoオーソライザーの設定によりエンドポイントやLamdba functionへのアクセス制御も可能です。
1.　ユーザープールにユーザーの認証情報を渡す
2.　認証情報が正しければChallengeというパラメータを返却する
3.　API GatewayにChallengeパラメータを渡す
4.　オーソライザーがChallengeパラメータを検証して正しければトークンを返却する
5.　トークンをもとにエンドポイントにアクセスする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737072/8dc3db0b-98d4-be62-43c1-411ad0936fa2.png)

https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html


### シナリオ3.AWSの別のサービスに対するアクセス権をユーザーに付与する
ユーザープールとIDプールを使用してAWSサービスにアクセスする方法です。

1.　ユーザープールにユーザーの認証情報を渡す
2.　認証情報が正しければトークンを返却する
3.　IDプールにトークンを渡す
4.　トークンが正しければ一時クレデンシャルキーを返却する
5.　一時クレデンシャルキーをもとに各AWSリソースにアクセスする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737072/abe80f9f-15a4-0046-9038-fdaed3659d19.png)


## 利用料金
https://aws.amazon.com/jp/cognito/pricing/

価格は変動するため利用する際に公式ページを見ていただければと思いますが、課金の仕組みだけご説明したいと思います。

料金が発生するコンポーネントはユーザープールとCognito Syncのみとなり、IDプール自体は無料で利用することが出来ます。(Cognito Syncはよく分かってないので割愛させてください)
ユーザープールは無期限の無料利用枠が用意されています。
ユーザープールのコストは月ごとのアクティブユーザ（サインイン、パスワード変更などが生じたユーザ）数で料金が加算される。使えば使うほどスケールメリットが働きコストダウンが発生します。
ユーザープールからの認証情報で直接サインインするユーザーと、SAML・フェデレーションを介してサインインするユーザーには、別々の料金が適用されます。

## 最後に
本記事ではCognitoの概要や機能のほんの一部分を切り取ってご紹介しましたが、公式ドキュメントやブログを見ていると、出来ることがありすぎてそもそも何から紹介するべきなのか迷いました。
ただ最初に理解しづらい箇所については抑えることができているのではないかなとも思います。
また、調査していく中で自分でも実装したことないが便利そうな機能があったので、次回はそれを踏まえてコードベースで実装方法を執筆できればなと思います。