概要
指定されたユーザー情報を使って、すぐにログインできるConfirmed状態のCognitoユーザーをバックエンド側でサクッと作成したい。
admin_create_user
だとForce Change Password状態となるので、この後に処理が必要。
今のところの結論
import boto3
username = '{ユーザー名}'
password = '{パスワード}'
email = '{メールアドレス}'
user_pool_id = '{ユーザープールID}'
client_id = '{アプリクライアントID}'
cognito_idp = boto3.client('cognito-idp')
# ユーザーを作成する。
cognito_idp.admin_create_user(
UserPoolId=user_pool_id,
Username=username,
TemporaryPassword=password,
UserAttributes=[{'Name': 'email', 'Value': email}],
MessageAction='SUPPRESS'
)
# ログインを試みる。(パスワードの変更を要求される。)
response = cognito_idp.admin_initiate_auth(
UserPoolId=user_pool_id,
ClientId=client_id,
AuthFlow='ADMIN_NO_SRP_AUTH',
AuthParameters={'USERNAME': username, 'PASSWORD': password},
)
session = response['Session']
# パスワードを変更する。
response = cognito_idp.admin_respond_to_auth_challenge(
UserPoolId=user_pool_id,
ClientId=client_id,
ChallengeName='NEW_PASSWORD_REQUIRED',
ChallengeResponses={'USERNAME': username, 'NEW_PASSWORD': password},
Session=session
)
解説
以下の3ステップでConfirmed状態のユーザーを作成しています。
- ユーザーの作成(
admin_create_user
) - 最初の認証(
admin_initiate_auth
) - パスワードの変更(
admin_respond_to_auth_challenge
)
1. ユーザーの作成(admin_create_user
)
管理者によるユーザーの作成を行う。
通常は作成した時に仮パスワードが通知されますが、MessageAction='SUPPRESS'
で無効にできます。
2. 最初の認証(admin_initiate_auth
)
管理者による最初の認証を試みる。
すると、以下のようなレスポンスが返却され、新しいパスワードが必要だということが分かります。この中のSession
が次の処理で必要となります。
{'ChallengeName': 'NEW_PASSWORD_REQUIRED',
'ChallengeParameters': (省略),
'ResponseMetadata': (省略),
'Session': '{セッションを表す長い文字列}'}
また、AuthFlow='ADMIN_NO_SRP_AUTH'
とする場合は、アプリクライアントの設定で「サーバーベースの認証でサインイン API を有効にする (ADMIN_NO_SRP_AUTH)」を有効にしておく必要があります。SRPというのは認証のプロトコルで、使用するとセキュアでない通信経路でもユーザー名とパスワードによる認証を安全に行なえるようになるようですが、実装が難しくなり、また今回は全てバックエンドでの処理となるので、使用しなくても良いこととしています。
3. パスワードの変更(admin_respond_to_auth_challenge
)
管理者によるNEW_PASSWORD_REQUIRED
に対する返答。
成功すると各種トークンが返却され、ユーザーの状態もConfirmedへ移行します。これでめでたくユーザーが普通にログインできるようになりました!
なお、コードにある通り、新しいパスワードは仮のパスワードと同じでも問題ありませんでした。
他の方法
一応、次の方法でもConfirmed状態のユーザーを作成することができます。
# ユーザーがサインアップする。
cognito_idp.sign_up(
ClientId=client_id,
Username=username,
Password=password,
UserAttributes=[{'Name': 'email',' Value': email}]
)
# それを管理者が承認する。
cognito_idp.admin_confirm_sign_up(
UserPoolId=user_pool_id,
Username=username
)
簡単だったので、最初はこちらの方法を使っていたのですが、アプリクライアントの設定で「アプリベースの認証でユーザー名とパスワードの (SRP を使用しない) フローを有効にする (USER_PASSWORD_AUTH)」を無効にしたり、属性の書き込み権限を変更したりするとsign_up
ができなくなるので、全て管理者の操作で行える上記の方法に変更しました。