こしあん
2024-12-10

一番簡単なCognitoの例を試す


11{icon} {views}


初めてAWS Cognitoを利用し、TerraformとPythonで認証の基本的な流れを試してみました。ユーザープールの作成から、ユーザー登録、確認、サインインまでの手順を解説します。

はじめに

Cognitoをちゃんと使ったことがなかったので使ってみた。やったことはGPTに「Cognitoの一番簡単な例を出してください」と言って出したもの。以下の通り

  • Cognitoのユーザープールとユーザープールクライアントを定義(Terraform)
  • Pythonコードからユーザー名、メールアドレスとパスワードを入力し、ユーザープールに登録(signup.py)
  • Pythonコードからメールアドレスに送られてくる認証コードを入力しユーザー確認(confirm_user.py)
  • Pythonコードからユーザー名とパスワードを入力し、サインインを行い、認証情報を得る

フロントエンドとのつなぎ込みは一切行っておらず、ただのPythonコードで行うのが最初のステップ。

Cognitoのユーザープールとユーザープールクライアントの作成

  • ユーザープールはユーザー情報と認証を管理する「場所」
  • ユーザープールクライアントはそのユーザープールにアクセスする「アプリケーション」の設定を定義

Terraformで行う。

# Cognitoユーザープールの作成
resource "aws_cognito_user_pool" "example" {
  name = "my-first-user-pool"

  # パスワードポリシーの設定(必要に応じて調整)
  password_policy {
    minimum_length    = 8
    require_uppercase = true
    require_lowercase = true
    require_numbers   = true
    require_symbols   = true
  }

  # ユーザー属性の設定
  auto_verified_attributes = ["email"]

  # その他の設定はデフォルトを使用
}

# ユーザープールクライアントの作成
resource "aws_cognito_user_pool_client" "example" {
  name         = "my-first-user-pool-client"
  user_pool_id = aws_cognito_user_pool.example.id

  # フロー設定(必要に応じて調整)
  explicit_auth_flows = [
    "ALLOW_USER_PASSWORD_AUTH",
    "ALLOW_REFRESH_TOKEN_AUTH",
  ]

  # リフレッシュトークンの有効期間(秒)
  refresh_token_validity = 30

  # クライアントシークレットの無効化(シンプルな例のため)
  generate_secret = false
}

# 出力変数の定義
output "user_pool_id" {
  description = "Cognito User Pool ID"
  value       = aws_cognito_user_pool.example.id
}

output "user_pool_client_id" {
  description = "Cognito User Pool Client ID"
  value       = aws_cognito_user_pool_client.example.id
}

terraform applyするとユーザープールIDと、ユーザープールクライアントのIDが出力する。これを後ほど使う。

user_pool_client_id = "1example23456789"
user_pool_id = "ap-northeast-1_ExaMPle"

ユーザー登録(signup.py)

# signup.py
import boto3
from botocore.exceptions import ClientError

# ユーザープールのIDとクライアントIDを設定
USER_POOL_ID = 'YOUR_USER_POOL_ID'       # 例: 'ap-northeast-1_ExaMPle'
CLIENT_ID = 'YOUR_APP_CLIENT_ID'        # 例: '1example23456789'
PROFILE_NAME = 'hogehoge'

# Cognito IDPクライアントを初期化
session = boto3.Session(profile_name=PROFILE_NAME)
client = session.client('cognito-idp')

def sign_up(username, password, email):
    try:
        response = client.sign_up(
            ClientId=CLIENT_ID,
            Username=username,
            Password=password,
            UserAttributes=[
                {
                    'Name': 'email',
                    'Value': email
                },
            ],
        )
        print(f"サインアップ成功。ユーザー名: {response['UserSub']}")
    except ClientError as e:
        print(f"サインアップエラー: {e.response['Error']['Message']}")

if __name__ == "__main__":
    username = 'testuser1'
    password = 'Password123!'  # パスワードポリシーに準拠していることを確認
    email = 'user@example.com' # メールを受信できるメールアドレスを入力
    sign_up(username, password, email)

成功すると以下のようなメッセージが出てくる。

サインアップ成功。ユーザー名: a1b2c3d4-e5f6-7890-ab12-c3d4e5f67890

ユーザー確認(confirm_user.py)

サインアップに成功すると、メールアドレスに確認コードが送られてくる。

次に以下のコードを実行し、ユーザーを認証させる。

# confirm_user.py
import boto3
from botocore.exceptions import ClientError

# ユーザープールのIDとクライアントIDを設定
USER_POOL_ID = 'YOUR_USER_POOL_ID'       # 例: 'ap-northeast-1_ExaMPle'
CLIENT_ID = 'YOUR_APP_CLIENT_ID'        # 例: '1example23456789'
PROFILE_NAME = 'hogehoge'

# Cognito IDPクライアントを初期化
session = boto3.Session(profile_name=PROFILE_NAME)
client = session.client('cognito-idp')

def confirm_user(username, confirmation_code):
    try:
        response = client.confirm_sign_up(
            ClientId=CLIENT_ID,
            Username=username,
            ConfirmationCode=confirmation_code,
        )
        print("ユーザー確認が成功しました。")
    except ClientError as e:
        print(f"ユーザー確認エラー: {e.response['Error']['Message']}")

if __name__ == "__main__":
    username = 'testuser1'
    confirmation_code = input("確認コードを入力してください: ")
    confirm_user(username, confirmation_code)

メールに送られたコードを入力すると確認に成功するはずである。

確認コードを入力してください: 123456
ユーザー確認が成功しました。

ユーザー確認が成功すると、マネジメントコンソールのCognitoユーザープールに「確認済み」と表示されるはずだ。

サインイン(signin.py)

このようにサインインをすると、

# signin.py
import boto3
from botocore.exceptions import ClientError

USER_POOL_ID = 'YOUR_USER_POOL_ID'       # 例: 'ap-northeast-1_ExaMPle'
CLIENT_ID = 'YOUR_APP_CLIENT_ID'        # 例: '1example23456789'
PROFILE_NAME = 'hogehoge'

session = boto3.Session(profile_name=PROFILE_NAME)
client = session.client('cognito-idp')

def sign_in(username, password):
    try:
        response = client.initiate_auth(
            ClientId=CLIENT_ID,
            AuthFlow='USER_PASSWORD_AUTH',
            AuthParameters={
                'USERNAME': username,
                'PASSWORD': password
            },
        )
        id_token = response['AuthenticationResult']['IdToken']
        access_token = response['AuthenticationResult']['AccessToken']
        refresh_token = response['AuthenticationResult']['RefreshToken']
        print("サインイン成功。")
        print(f"IDトークン: {id_token}")
        print(f"アクセストークン: {access_token}")
        print(f"リフレッシュトークン: {refresh_token}")
    except ClientError as e:
        print(f"サインインエラー: {e.response['Error']['Message']}")

if __name__ == "__main__":
    username = 'testuser1'
    password = 'Password123!'
    sign_in(username, password)

様々なトークンが出てくる。

IDトークン: eyJraWQiOiJ6MU......
アクセストークン: eyJraWQiOiJ4......
リフレッシュトークン: eyJjdHkiOiJK......

これで簡単なCognitoによる簡単な例を確認できた。



Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内

技術書コーナー

北海道の駅巡りコーナー


Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です