0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【AWS】Lambdaにフロント側からデータを渡す

Last updated at Posted at 2023-01-21

背景

AWS LambdaでAmazon Cognitoのメールアドレスや電話番号を変更時にフロント側から送られてくるデータを使用して重複チェックをしたい時があって、少しつまづいたのでどうにかできないかということがありました。

変更のタイミングでAmazon Cognito側のLambdaトリガーを使って実装していたのですが、トリガー発火した時のeventの中身には登録されているAmazon Cognitoのユーザープールのデータが取れるので、フロント側から変更したデータは得られていないことが発覚。

API Gatewayをトリガーにしたらデータも取得できるので可能ですが、今回はAmazon Cognito + AWS Lambdaでの実装が必要だということだったので、別の方法が必要でした。

解決方法

今回はフロント側からAmplifyのAuthを使用した方法で変更のデータが送られるので、そのときにClientMetadataを送信することで対応しました。

ただ、状況によってはClientMetadataの使用が非推奨のこともあるので、実装する際は要件などに気をつける必要がありそうです。

実行環境

Python 3.9

実装コード(例)

フロント側(React)

今回はAmazon Cognitoのメールアドレスの属性を変更するので、変更のメールアドレスのデータをAuth.updateUserAttributesの引数に渡します。

ここでClientMetadataに該当する第3引数にdataを渡すことでバックエンド(Lambda)側でデータを使うことができます。

import { Auth } from '@aws-amplify';
import { Authenticator } from '@aws-amplify/ui-react';

function App() {
    const changeAttribute = async () => {
        const user = await Auth.currentAuthenticatedUser(); // ログインしているユーザーデータ
        const data = {'email': 'xxxxxx@example.com'}; // 変更するデータ(今回はメールアドレス)

        return await Auth.updateUserAttributes(
            user,
            data,
            data // ClientMetadataの引数
        );

    return (
        <Authenticator>
            {({ signOut, user }) => (
                <div>
                    <button onClick={signOut}>Sign Out</button>
                    <button onClick={changeAttribute}>Change Attribute</button>
                </div>
            )}
        </Authenticator>
    );
}

バックエンド側(Python)

バックエンド(Lambda)側では、Amazon CognitoのLambdaトリガーから渡されるevent内にフロント側から送信されたClientMetadataevent['request']['clientMetadata']で取得できます。

import boto3

def lambda_handler(event, context):
    if event['triggerSource'] == 'CustomMessage_UpdateUserAttribute':
        try:
            if event['request']['clientMetadata'].get('email') is not None:
                duplicated_user = cognito_client.list_users(
                    UserPoolId = event['userPoolId'],
                    Filter = f"email =\"{ event['request']['clientMetadata']['email'] }\""
                )
                
                if len(duplicated_user['Users']) > 0:
                    raise Exception('このメールアドレスはすでに登録されています。べつのメールアドレスを登録してください。')
            
            return event
        
        except Exception as e:
            print(e)
        

これで、変更したいメールアドレスのユーザーがすでに存在していた場合は、エラーを発生させます。

注意点

AWS SDK for Python(boto3)公式サイトにClientMetadataの使用上の注意が書かれています。
表記は英語なので簡単に翻訳して引用します。

ClientMetadataパラメーターを使う場合、Amazon Cognitoは以下のことをしないということに注意してください:

①ClientMetadataの値を保存しません。
また、このデータはCognitoのユーザープールに設定されたLambdaトリガーでのみ使用可能です。

②ClientMetadataの値はバリデーションされません。

③ClientMetadataの値は暗号化されません。
そのため、暗号化が必要なデータなどの送信はしないようにしてください。

このような注意点がありますので、上述のように要件などに合わせて使う必要があります。

まとめ

AWSを触り始めてまだ1か月ほどで、ここまで来るのに苦労しました...

解決したかと思いきや、注意点もあったのでなんともいいがたいところです...

もしほかの方法やご指摘がありましたら、コメントにお願いいたします!

引用記事等

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.get_user

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?