サーバレスアーキテクチャにおけるアクセス制御について

# はじめに

Webサービスには、認証・認可が必要な場合が多く、それをアプリで実現しようとすると手間が掛かります。
サーバレスアーキテクチャでは、認証・認可をAWSのサービスをうまく使って実装することで、開発にかかる期間を短縮できます。
また、IDやパスワード忘れなどのよくある問い合わせにも、一切コードを書かずに対応できる仕組みがあります。


# 認証と認可

混同しがちなのですが、認証と認可を改めて確認してください。

よくわかる認証と認可
https://dev.classmethod.jp/articles/authentication-and-authorization/

## 認証

通信の相手が誰(何)であるかを確認すること。

## 認可

とある特定の条件に対して、リソースアクセスの権限を与えること。


# AWSサービスそれぞれの役割

API Gateway、Cognito、Lambdaの3つの役割を記載します。

- API Gatewayは、アプリケーションがバックエンドサービスからのデータ、ビジネスロジック、機能にアクセスするための「フロントドア」として機能します。
- Cognitoは、ウェブアプリケーションおよびモバイルアプリに素早く簡単にユーザーのサインアップ/サインインおよびアクセスコントロールの機能を追加できます。
- AWS Lambda を使用することで、サーバーのプロビジョニングや管理をすることなく、コードを実行できます。料金は、コンピューティングに使用した時間に対してのみ発生します。


# Cognitoから発行されるトークン

Cognitoから発行されるトークンは、3種類あります。
認証で必要となるので、覚えておいてください。

- IDトークン(IDToken)
- アクセストークン(AccessToken)
- 更新トークン(RefreshToken)

## IDトークン(IDToken)

Cognito User Poolsのユーザー属性を含めたトークンです。
API Gatewayでは、こちらのトークンを使用します。
認証後、3600秒後(1時間後)で有効期限切れになります。

## アクセストークン(AccessToken)

Cognito User Poolsの最低限のユーザー情報を含めたトークンです。
認証後、3600秒後(1時間後)で有効期限切れになります。

## 更新トークン(RefreshToken)

IDトークンは、1時間後に有効期限切れになるため、有効期限が切れたら更新トークンを使用して、新しいIDトークンを発行します。
更新トークンは、デフォルトで30日後に有効期限切れとなり、有効期限が切れたらサインインが必要となります。

- デフォルトで30日になっていますが、1日〜3650日まで期間を変更することが出来ます。
- AWS SDK(Amplify)を使用している場合は、更新トークンによって自動的にIDトークンが更新されますので、特に操作(ロジック)は不要です。


# API Gatewayの認証方法

いくつかパターンがあるので、1つずつ解説していきます。

- IAM認証 + Cognito
- Cognitoユーザープールオーソライザー
- Lambdaオーソライザー
- APIキー
- Cognito + Lambdaオーソライザー


## IAM認証 + Cognito

IAM認証とCognitoを組み合わせる方法。
CognitoがIAMを返して、そのIAMに基づいて、API GatewayはLambdaを実行しようとします。

![認証認可-IAM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150734/22f19c05-140d-607d-2e2b-7a76bad7fd23.jpeg)


## Cognitoユーザープールオーソライザー

Cognitoでユーザ認証ができるか確認する方法。
IAM認証 + Cognitoと異なり、フェデレーティッドアイデンティティは使用しないし、IAMも使用しません。

![認証認可-cognito.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150734/9a8d2516-2769-236e-5f24-22350d7fe273.jpeg)

## Lambdaオーソライザー

Lambdaに独自の認証ロジックを書く方法。
Lambdaに独自の認証ロジック(Authorizationヘッダにセットしたトークンの検証等)を記述でき、認証する場合、Lambdaを実行可能なIAMポリシーを生成してreturnすると、Lambdaを実行する

![認証認可-Lambda.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150734/715d38e7-92a1-056a-1cf7-b1d43c886df6.jpeg)

## APIキー

APIキーでアクセス制限する。APIキーをx-api-keyヘッダに設定したときのみLambdaを実行する。
AWSは認証機能として使用しないようにドキュメントに記載しているが、一般ユーザ間の通信ではなくサーバ間のAPI通信などAPIキーが外部に漏れない状況であれば、簡易的な認証として使用できる。

![認証認可-APIキー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150734/fac763f9-4af9-c37e-9d20-8ac645a4a0db.jpeg)


## Cognito + Lambdaオーソライザー

Cognitoでユーザ認証ができるか確認し、Lambdaオーソライザーで認可の処理を実装する方法。

![認証認可-Cognito_Lambda.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150734/c04a3aff-9d42-9722-842a-22017c9f5285.jpeg)


# 認証方式と利用方法

ユーザーにAPI Gateway コンポーネントサービスを呼び出す権限が与えられ、Lambdaの実行が可能となります。

|認証方法|利用用途|
|:-----------------|:-----------------|
|IAM認証 + Cognito|ログイン済みユーザと、ゲストユーザーの2種類で、Lambdaの実行可否を制御するのに向いている。|
|Cognitoユーザープールオーソライザー|認証できれば、Lambdaを実行可能とするのに向いている。|
|Lambdaオーソライザー|独自の認証・認可ロジックを書けるが、それなりにしんどい。|
|APIキー|APIキーが漏洩する可能性が低い、サーバ間API連係等に向いている。|
|Cognito + Lambdaオーソライザー|クライアントでCognito認証を行い、Lambdaで独自認可処理を行う場合に向いている。認証と認可のロジックが分離できる。|


# まとめ

- 認証不要な場合は、API Gateway+Lambdaの構成
- サーバー間通信の場合は、シンプルなAPIキー
- 認証済みの場合に限り、特定のLambdaを実行したい場合は、IAM認証+Cognito
- 認証できれば誰でも使っていい場合は、Cognitoユーザープールオーソライザー
- WebクライアントでAWS SDKが使えない場合は、Lambdaオーソライザーで頑張る
- WebクライアントでAWS SDKが使える場合は、Cognito認証を実装し、Lambdaオーソライザーで認可