【教えて下さい】CognitoでS3にOAuth認証してみた

# はじめに
- Amazon Cognitoを使ってS3の静的ウェブサイトに認証をかけてみました
- CloudFrontのLambda@Edgeを組み合わせ、Google OAuthを利用したログインを実現しています
- ですが、私自身もまだ完全には理解できていない部分が多いため、実際の設定手順や試行錯誤のプロセスを共有し、有識者の方からのフィードバックをいただけると嬉しいです


# やったことの概要
1. S3バケットの作成
    - 静的コンテンツを格納するためのS3バケットを作成しました
2. CloudFrontのオリジンとして設定
    - S3バケットをCloudFrontのオリジンに設定し、OAC (Origin Access Control) を使用してセキュアにアクセスできるようにしました
3. GCPでOAuth同意画面を作成
    - Cognitoと連携するため、Google Cloud Platform (GCP) 上でOAuth同意画面を作成しました
4. Amazon Cognitoユーザープールの作成
    - Cognitoのユーザープールを作成し、IDプロバイダーとしてGoogleを設定しました
5. Lambda関数の作成
    - 認証フローやログアウト処理を行うためのLambda関数をPythonで実装しました
6. CloudFrontのLambda@Edgeに設定
    - CloudFrontのビューワーリクエストイベントに対し、Lambda@Edgeとして設定しました



# S3にバケットを作る
- バケットを作成
- パブリックアクセスは許可しない
![S3_バケットを作成___S3___ap-northeast-1_20241114_170113.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/0dcb1d26-d73d-b089-8207-447de29fd886.png)
![S3_バケットを作成___S3___ap-northeast-1_20241114_170158.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/87ae0cb8-4e7c-e7af-95a9-536f40048841.png)
- 認証が必要なページのhtmlをバケットにおく
- パブリックアクセスをブロックしているのでブラウザで開けない
![oguro-052864411610_s3_ap-northeast-1_amazonaws_com_index_html_20241114_172227.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/cb786426-764b-3510-3cc5-cbfa48d64f2d.png)


# CloudFrontでディストリビューションを作る
- OACを作る
![Cursor_と_Amazon_CloudFront_20241114_171111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/eeed77f7-99d2-406d-5d5a-1f2252235bba.png)
- ディストリビューションを作成
- キャッシュのあたりがよくわかってない・・
![Amazon_CloudFront_20241114_171157.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/d8d49a9d-88da-8d6b-d7d9-1560218f9c4e.png)
![Cursor_と_Amazon_CloudFront_20241114_171321.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/ad23f7c5-8ec0-385b-1658-e139b42f4dd6.png)
![Cursor_と_Amazon_CloudFront_20241114_171335.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/b62f5d43-0276-368a-1af5-cc783fe4ac11.png)

- ディストリビューションを作ると画面上部に出てくる
- コピーして、バケットポリシーに貼り付ける
![Amazon_CloudFront_20241114_171416.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/90df9ae7-3882-201e-3a90-774b8ade1401.png)
![バケットポリシーを編集_-_S3_バケット_oguro-052864411610___S3___ap-northeast-1_20241114_171523.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/3cf831f9-2069-e613-3d7e-731545c6c17b.png)
- これで、CloudFrontを経由すればブラウザで開くようになる
![認証成功_20241114_172058.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/e8d0d8e9-b6b4-0510-b484-ffd3b7be21a8.png)


# GCPでOAuth 同意画面とクライアントを作る
- 新しいプロジェクト
![新しいプロジェクト_–_gravityga_jp_–_Google_Cloud_コンソール_20241114_174436.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/14ca4d7f-2c9f-071f-2692-5297323293be.png)
![Cursor_と_API_とサービス_–_oguro-cognito_–_Google_Cloud_コンソール_20241114_174558.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/17389426-7948-f04b-af34-273b4d0b5a8a.png)
![アプリ登録の編集_–_API_とサービス_–_oguro-cognito_–_Google_Cloud_コンソール_20241114_175027.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/654f0e5f-c736-2d3f-57ef-1ad80eaa0b29.png)

## User Type
- `内部`
    - GCPプロジェクトが組織に属している場合
        - Google Workspaceのユーザーだけが通過できる
    - GCPプロジェクトが組織に属していない場合
        - 誰も通過できない
    - `外部`
    - Googleアカウントなら誰でも通過できる

## 認証情報を作成する
- OAuth クライアントID
![Cursor_と_認証情報_–_API_とサービス_–_oguro-cognito_–_Google_Cloud_コンソール_20241114_175227.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/f3b3fd06-150a-1120-9f7d-eacb1745ec2f.png)
![Cursor_と_OAuth_クライアント_ID_の作成_–_API_とサービス_–_oguro-cognito_–_Google_Cloud_コンソール_20241114_175313.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/ff327841-2fa6-9cb4-2eb0-288bf598b979.png)
![認証情報_–_API_とサービス_–_oguro-cognito_–_Google_Cloud_コンソール_20241114_175348.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/14bf0316-fe9d-4ff6-c1e5-4e5407a8e920.png)
- 承認済みのリダイレクト URIは後で設定が必要になる
- クライアントIDとシークレットをメモっておく


# Cognitoでユーザープールを作る
- ユーザープールを作成
![ユーザープールを作成___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241114_175746.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/0e2fa6e9-7aa3-9d67-f29e-6948fa94956b.png)
![ユーザープールを作成___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241114_175801.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/e8ec2734-ac37-20c0-371a-4b4a97cc024f.png)
    - Eメール
    - Google
- セキュリティ要件を設定
![ユーザープールを作成___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241114_175846.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/cad446db-a111-42c4-a87d-7259f016de8f.png)
![ユーザープールを作成___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241114_175857.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/e6d8c27e-fb25-1da7-e44b-7945295a1ada.png)
    - MFAなし
- サインアップエクスペリエンスを設定
![ユーザープールを作成___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241114_180006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/1794e0e4-6ddc-6c32-dce4-0131aa080efa.png)
![Cursor_と_ユーザープールを作成___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241114_180038.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/6cdf3ae5-0e61-0b4e-c195-527e6da84cef.png)
    - 自己登録を有効化 のチェックを外す
- メッセージ配信を設定
![ユーザープールを作成___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241114_180144.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/b3896bc4-fd5a-8626-d332-12723119ca62.png)
    - CognitoでEメールを送信
- フェデレーテッドアイデンティティプロバイダーを接続
![Cursor_と_ユーザープールを作成___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241114_180438.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/92df17d5-cfc5-18d2-ee25-914e96bd825a.png)
    - さっきGCPで作ったクライアントの情報を貼り付ける
    - 許可されたスコープ
        - `openid email profile`
- アプリケーションを統合
![ユーザープールを作成___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241114_181343.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/881c8805-7702-9e7e-9458-91c620cf7801.png)
![ユーザープールを作成___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241114_181417.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/698b0608-0301-a6b7-a0d9-39bcaf4d77a1.png)
![ユーザープールを作成___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241114_181502.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/02468032-e2ae-955a-f2aa-0151f14e7965.png)
    - Cognito ドメインを使用する
    - クライアントのシークレットは生成する
    - リダイレクトURI
        - https://dj4ve2s8yqfir.cloudfront.net/index.html

# Lambdaを作る
- SAMで作った
- us-east-1にデプロイする
```cognito_jwt_validator.py
import json
import base64

# ======== 設定 ========
COGNITO_POOL_ID = "ap-northeast-1_yeeHL6sOj"
COGNITO_CLIENT_ID = "5a1aiip7crdbaosrq0rnlnop91"
COGNITO_HOST_UI_DOMAIN = "oguro-google-01"
CLOUDFRONT_DOMAIN = "dj4ve2s8yqfir"

COGNITO_ISSUER = f"https://cognito-idp.ap-northeast-1.amazonaws.com/{COGNITO_POOL_ID}"
REDIRECT_URL = (
    f"https://{COGNITO_HOST_UI_DOMAIN}.auth.ap-northeast-1.amazoncognito.com/login"
    f"?client_id={COGNITO_CLIENT_ID}&response_type=code"
    f"&scope=openid&redirect_uri=https://{CLOUDFRONT_DOMAIN}.cloudfront.net/token"
)

# JWTトークンの簡易検証
def validate_jwt_simplified(token):
    try:
        # トークンをヘッダー、ペイロード、署名に分割
        parts = token.split('.')
        if len(parts) != 3:
            print("トークンの形式が不正です。")
            return False

        # ペイロード部分をデコード
        payload_encoded = parts[1]
        payload_decoded = base64.urlsafe_b64decode(payload_encoded + '=' * (-len(payload_encoded) % 4))
        payload = json.loads(payload_decoded)

        # 最低限のフィールド検証
        if payload.get("iss") != COGNITO_ISSUER:
            print("発行者が一致しません。")
            return False
        if payload.get("aud") != COGNITO_CLIENT_ID:
            print("オーディエンスが一致しません。")
            return False

        print("トークンは有効です。")
        return True
    except Exception as e:
        print(f"トークン検証中にエラーが発生しました: {e}")
        return False


# Cookieを解析して辞書形式に変換
def parse_cookies(headers):
    parsed_cookie = {}
    if 'cookie' in headers:
        for cookie in headers['cookie']:
            for item in cookie['value'].split(';'):
                parts = item.split('=')
                if len(parts) == 2:
                    parsed_cookie[parts[0].strip()] = parts[1].strip()
    return parsed_cookie


# Cookieから指定されたトークンを取得
def get_token_from_cookies(headers, token_name):
    cookies = parse_cookies(headers)
    return cookies.get(token_name)


# Lambdaハンドラー
def lambda_handler(event, context):
    print(event)
    request = event['Records'][0]['cf']['request']

    # クッキーからIDトークンを取得
    token = get_token_from_cookies(request['headers'], 'id_token')
    print(f"取得したトークン: {token}")

    # トークンが無い場合はリダイレクト
    if not token:
        return {
            'status': '302',
            'statusDescription': 'Found',
            'headers': {
                'location': [{'key': 'Location', 'value': REDIRECT_URL}]
            }
        }

    # トークン検証
    try:
        if validate_jwt_simplified(token):
            print("トークン検証成功")
        else:
            raise ValueError("トークンの検証に失敗しました")
    except Exception as e:
        print(f"認証エラー: {e}")
        return {
            'status': '302',
            'statusDescription': 'Found',
            'headers': {
                'location': [{'key': 'Location', 'value': REDIRECT_URL}]
            }
        }

    # 認証成功の場合、リクエストを通す
    return request
```

```cognito_token_redirect.py
import requests
import json
import urllib.parse
import base64

# 設定
COGNITO_CLIENT_ID = "5a1aiip7crdbaosrq0rnlnop91"
COGNITO_CLIENT_SECRET = "2kfjic08vg45ug3dso7uctsv9nmp4*************"
COGNITO_HOST_UI_DOMAIN = "oguro-google-01"
CLOUDFRONT_DOMAIN = "dj4ve2s8yqfir"
REDIRECT_URI = f"https://{CLOUDFRONT_DOMAIN}.cloudfront.net/token"
REDIRECT_AFTER_AUTH = f"https://{CLOUDFRONT_DOMAIN}.cloudfront.net/index.html"

# 認証情報をBase64エンコードで生成
def get_authorization():
    auth_str = f"{COGNITO_CLIENT_ID}:{COGNITO_CLIENT_SECRET}"
    return base64.b64encode(auth_str.encode("utf-8")).decode("utf-8")

# Authorization Codeを使用してトークンを取得
def get_tokens_from_code(code):
    authorization = get_authorization()
    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
        "Authorization": f"Basic {authorization}"
    }
    data = {
        "grant_type": "authorization_code",
        "client_id": COGNITO_CLIENT_ID,
        "redirect_uri": REDIRECT_URI,
        "code": code
    }

    token_url = f"https://{COGNITO_HOST_UI_DOMAIN}.auth.ap-northeast-1.amazoncognito.com/oauth2/token"
    response = requests.post(token_url, headers=headers, data=data)

    if response.status_code == 200:
        tokens = response.json()
        return tokens.get("access_token"), tokens.get("id_token")
    else:
        raise Exception(f"Failed to obtain tokens: {response.status_code} - {response.text}")

# Lambdaハンドラー
def lambda_handler(event, context):
    # CloudFrontリクエストの取得
    request = event['Records'][0]['cf']['request']

    # クエリ文字列の解析
    params = urllib.parse.parse_qs(request['querystring'])
    code = params.get('code', [None])[0]  # 'code' パラメータの取得

    if not code:
        return {
            'statusCode': 400,
            'body': json.dumps("Code parameter is missing in the URL.")
        }

    try:
        # トークン取得
        access_token, id_token = get_tokens_from_code(code)

        # クッキー設定
        cookie_value = f"id_token={id_token}; Secure; HttpOnly; SameSite=None; Path=/"

        return {
            'status': '302',
            'statusDescription': 'Found',
            'headers': {
                'location': [{
                    'key': 'Location',
                    'value': REDIRECT_AFTER_AUTH
                }],
                'set-cookie': [{
                    'key': 'Set-Cookie',
                    'value': cookie_value
                }],
                'cache-control': [{
                    'key': 'Cache-Control',
                    'value': 'no-cache, no-store, must-revalidate'
                }],
                'pragma': [{
                    'key': 'Pragma',
                    'value': 'no-cache'
                }],
                'expires': [{
                    'key': 'Expires',
                    'value': '0'
                }]
            }
        }

    except Exception as e:
        return {
            'statusCode': 500,
            'body': json.dumps(f"Error occurred: {str(e)}")
        }
```

```cognito_logout_handler.py
import json

# 設定
COGNITO_CLIENT_ID = "5a1aiip7crdbaosrq0rnlnop91"
COGNITO_HOST_UI_DOMAIN = "oguro-google-01"
CLOUDFRONT_DOMAIN = "dj4ve2s8yqfir"
LOGOUT_REDIRECT_URI = f"https://{CLOUDFRONT_DOMAIN}.cloudfront.net/index.html"

# CognitoのログアウトURLを構築
def build_cognito_logout_url():
    return (
        f"https://{COGNITO_HOST_UI_DOMAIN}.auth.ap-northeast-1.amazoncognito.com/logout"
        f"?client_id={COGNITO_CLIENT_ID}&logout_uri={LOGOUT_REDIRECT_URI}"
    )

# Lambdaハンドラー
def lambda_handler(event, context):
    # CognitoのログアウトURL
    cognito_logout_url = build_cognito_logout_url()

    # クッキー削除のためのSet-Cookieヘッダー
    set_cookie_headers = [
        {
            'key': 'Set-Cookie',
            'value': 'id_token=; Max-Age=0; Path=/; Secure; HttpOnly; SameSite=None'
        },
        {
            'key': 'Set-Cookie',
            'value': 'access_token=; Max-Age=0; Path=/; Secure; HttpOnly; SameSite=None'
        },
        {
            'key': 'Set-Cookie',
            'value': 'refresh_token=; Max-Age=0; Path=/; Secure; HttpOnly; SameSite=None'
        }
    ]

    # レスポンスを構築
    response = {
        'status': '302',  # リダイレクト
        'statusDescription': 'Found',
        'headers': {
            'location': [{
                'key': 'Location',
                'value': cognito_logout_url  # CognitoのログアウトURLにリダイレクト
            }],
            'set-cookie': set_cookie_headers,
            'cache-control': [{
                'key': 'Cache-Control',
                'value': 'no-cache, no-store, must-revalidate'
            }],
            'pragma': [{
                'key': 'Pragma',
                'value': 'no-cache'
            }],
            'expires': [{
                'key': 'Expires',
                'value': '0'
            }]
        }
    }

    return response
```

```template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  Serverless Application Model Template for Cognito authentication and logout
  with Python-based Lambda functions.

Globals:
  Function:
    Timeout: 3
    MemorySize: 128

Resources:
  ValidateCognitoJWTFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: cognito_jwt_validator.lambda_handler
      Runtime: python3.12
      Architectures:
        - x86_64
      Description: Validates JWT tokens issued by Cognito.

  CognitoTokenRedirectFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: cognito_token_redirect.lambda_handler
      Runtime: python3.12
      Architectures:
        - x86_64
      Description: Handles redirect from Cognito and processes access tokens.

  CognitoLogoutHandlerFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: cognito_logout_handler.lambda_handler
      Runtime: python3.12
      Architectures:
        - x86_64
      Description: Logs out users from Cognito and clears authentication cookies.

Outputs:
  ValidateCognitoJWTFunction:
    Description: ARN of the ValidateCognitoJWTFunction
    Value: !GetAtt ValidateCognitoJWTFunction.Arn

  CognitoTokenRedirectFunction:
    Description: ARN of the CognitoTokenRedirectFunction
    Value: !GetAtt CognitoTokenRedirectFunction.Arn

  CognitoLogoutHandlerFunction:
    Description: ARN of the CognitoLogoutHandlerFunction
    Value: !GetAtt CognitoLogoutHandlerFunction.Arn
```

# CloudFrontにビヘイビアを作る
- /token /logout の２つ
![Cursor_と_Amazon_CloudFront_20241116_124022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/84279709-6db2-2dca-908b-94aab46467c4.png)

# CloudFrontのLambda@Edgeに登録する
- まずはロールを追加する
![sam-cognito-python-google-ValidateCognitoJWTFuncti-0n9oz1fxHCva___関数___Lambda_20241116_125140.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/f531ba9f-853f-7ba0-560d-bdb09e900447.png)
![sam-cognito-python-google-ValidateCognitoJWTFuncti-0n9oz1fxHCva___関数___Lambda_20241116_125103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/fc3bc46f-17cf-beaa-16c4-4a2be5649e85.png)
![sam-cognito-python-google-ValidateCognitoJWTFuncti-0n9oz1fxHCva___関数___Lambda_20241116_125219.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/fa9e614b-5946-bd55-e438-43ee74fd8c2c.png)
![sam-cognito-python-google-ValidateCognitoJWTFunctio-cWoasxnRR7r2___IAM___Global_20241116_125339.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/0ef3203d-7e55-b0dd-ce78-16dfbec3c328.png)
- CloudFrontのLambda@Edgeに設定される
![Cursor_と_Amazon_CloudFront_20241116_193750.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/e8276270-24d8-3f1e-0fe0-0e330cad5a60.png)

# 3つのLambdaをそれぞれのビヘイビアに登録する
- デフォルト (*)
    - ValidateCognitoJWTFunc
- /logout
    - CognitoLogoutHandlerFunc
- /token
    - CognitoTokenRedirectFunc


# Cognitoの設定を修正
- ホストされたUIを編集
![ホストされた_UI_を編集___アプリケーションクライアント__oguro-google-client___oguro-cognito-pool___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241116_195002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/76c5213f-5185-1c84-b7c0-386bc7fba4b9.png)
![ホストされた_UI_を編集___アプリケーションクライアント__oguro-google-client___oguro-cognito-pool___ユーザープール___Amazon_Cognito___ap-northeast-1___Cognito___ap-northeast-1_20241116_195017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/b4306cea-3a6e-5e43-ca96-eecd6842c024.png)
    - コールバックURLを修正
    - サインアウトURLを修正
    - IDプロバイダーからCognitoユーザープールを削除

# GCPの設定を変更
- 承認済みのリダイレクト URI
    - https://oguro-google-01.auth.ap-northeast-1.amazoncognito.com/oauth2/idpresponse


# 動作確認
- https://dj4ve2s8yqfir.cloudfront.net/index.html
![Signin_20241116_200541.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/1eac2440-5dcb-cfed-5d22-1722969f128b.png)
![ログイン_-_Google_アカウント_20241116_200636.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/c404cce7-2344-f217-5dd1-b14b8e2c7a15.png)
![認証成功_20241116_200755.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/ae6d37cc-913c-a68e-4bbf-e4dab643d870.png)
- 組織外のGoogleアカウントは入れない
![ログイン_-_Google_アカウント_20241116_200710.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909910/a5204c7d-e778-0ad9-c957-c64a3d0995c7.png)

# 自己フィードバック
- Cognitoの設定に関して苦戦しました
    - 「パブリッククライアント」と「秘密クライアント」の違いがいまいち理解できていません
    - クライアントシークレットを生成しましたが、これが正しい対応だったのか不明です
- Lambdaのコードについて
    - シークレットを直接コード内に書いてしまいました（反省しています）
    - JWTを扱うパッケージが大きすぎたので、チェックが簡易版です・・
    - Pythonで実装しましたが、認証周りではNode.jsの方が適しているようなので、そちらで作り直そうと考えています



# さいごに
- Cognitoは予想以上に難しかったです・・
- 一応動くものは作れましたが、自分でも改善点が多いと感じています
- 有識者の皆さまからアドバイスやフィードバックをいただけると非常に助かります！
- 作成したものは現在、セキュリティの観点から停止済みです