タイトルの通りです。
普段はnode(typescript)とかでアプリケーションの構築(APIサーバー)してます。
cognitoでユーザーごとにMFA有効にしようとしたらどうすればいいかを検証した備忘録を以下に記します。
前提
- cognitoのuserPoolは作ってある
- emailでのログインを許可してる
- クライアントも作成してる
- 有効にするのはTOTPでのMFA
- 検証レベルなので、awsCliを使う
- configはすでに設定してある
MFA = requiredはuserPool作成時しか設定できない
ドキュメントは以下
必須以外なら変更できる
off <-> optional は可能。
スクリーンショットの通り。
cognito > MFA and verifications にて設定可能。
optionalにし、TOTPにチェックを入れておく。


signupとconfirm
$ aws cognito-idp sign-up --client-id [clientId] --username [email] --password [password]
{
"UserConfirmed": false,
"CodeDeliveryDetails": {
"Destination": "[一部マスクされたemail]",
"DeliveryMedium": "EMAIL",
"AttributeName": "email"
},
"UserSub": "[userSub]"
}
$ aws cognito-idp confirm-sign-up --client-id [clientId] --username [email] --confirmation-code [メールで送られてきたconfirmationCode]
まずはログインしてみる
MFA = off
の時と同じレスポンス
$ aws cognito-idp admin-initiate-auth --user-pool-id [userPoolId] --client-id [clientId] --auth-flow ADMIN_NO_SRP_AUTH --auth-parameters USERNAME=[email],PASSWORD=[password]
{
"ChallengeParameters": {},
"AuthenticationResult": {
"AccessToken": "[accessToken]",
"ExpiresIn": 3600,
"TokenType": "Bearer",
"RefreshToken": "[refreshToken]",
"IdToken": "[idToken]"
}
}
MFAの有効化
$ aws cognito-idp associate-software-token --access-token [accessToken]
{
"SecretCode": "[secretCode]"
}
googleAuthenticator等で、このコードを登録するか、このコードからQRコードを生成して読み取る
トークンの検証
$ aws cognito-idp verify-software-token --access-token [accessToken] --user-code [googleAuthenticator等で発行されてるトークン]
{
"Status": "SUCCESS"
}
ユーザーにMFA設定をセット
TOTPを有効かつ優先にする設定
(優先もなにもこのuserPoolにはTOTPしか許可してないけど)
$ aws cognito-idp admin-set-user-mfa-preference --username [userName] --user-pool-id [userPoolId] --software-token-mfa-settings Enabled=true,PreferredMfa=true
設定完了後にログインしてみる
さきほどのログインとはレスポンスが異なる。
ログインに挑戦しましょう。成功したらaccessToken渡すよ
的な状態になってる。
ので、続いてMFAのトークン検証も通れば、accessTokenが返る。
USER_ID_FOR_SRP
は、 USER_ID_FOR_SRP === userName === sub
となっているので、uuid的なのが表示されてる。
$ aws cognito-idp admin-initiate-auth --user-pool-id [userPoolId] --client-id [clientId] --auth-flow ADMIN_NO_SRP_AUTH --auth-parameters USERNAME=[email],PASSWORD=[password]
{
"ChallengeName": "SOFTWARE_TOKEN_MFA",
"Session": "[session]",
"ChallengeParameters": {
"USER_ID_FOR_SRP": "[uuid的なやつ]"
}
}
ログイン時のトークン検証
sessionやchallengeNameなど、 admin-initiate-auth
のレスポンスを使う。
$ aws cognito-idp admin-respond-to-auth-challenge --user-pool-id [userPoolId] --client-id [clientId] --challenge-name SOFTWARE_TOKEN_MFA --session [session] --challenge-responses USERNAME=[admin-initiate-authのレスポンスのUSER_ID_FOR_SRP],SOFTWARE_TOKEN_MFA_CODE=[googleAuthenticator等で発行されてるトークン]
{
"ChallengeParameters": {},
"AuthenticationResult": {
"AccessToken": "[accessToken]",
"ExpiresIn": 3600,
"TokenType": "Bearer",
"RefreshToken": "[refreshToken]",
"IdToken": "[idToken]"
}
}
ドキュメント見ても、 --challenge-responses
のパラメータの記載見つけられなくて困惑した。
エラー吐かせて足りないパラメータ確認するを繰り返した。
各チャレンジに対応した --challenge-responses
のパラメータの記載が網羅されているものがあれば教えていただけないでしょうか...。
ちなみに
associate前にsetしようとすると以下のように怒られるので、cognitoAPIの実行順に注意です。
associate-software-token
=> admin-set-user-mfa-preference
の順番で!
An error occurred (InvalidParameterException) when calling the AdminSetUserMFAPreference operation: User has not set up software token mfa
typescriptの場合
僕が実際にAPIに組み込む時はこれをtsで使う必要がある。
jsのawsSdkだと以下が同様のcognitoAPI(だと思う)
new CognitoIdentityServiceProvider().adminInitiateAuth();
new CognitoIdentityServiceProvider().associateSoftwareToken();
new CognitoIdentityServiceProvider().adminSetUserMFAPreference();
new CognitoIdentityServiceProvider().verifySoftwareToken();
new CognitoIdentityServiceProvider().adminRespondToAuthChallenge();