AWS
MFA
cognito

AWS CognitoでMFA = OPTIONALにし、ユーザーごとに有効にする

タイトルの通りです。

普段はnode(typescript)とかでアプリケーションの構築(APIサーバー)してます。

cognitoでユーザーごとにMFA有効にしようとしたらどうすればいいかを検証した備忘録を以下に記します。


前提


  • cognitoのuserPoolは作ってある


    • emailでのログインを許可してる

    • クライアントも作成してる



  • 有効にするのはTOTPでのMFA

  • 検証レベルなので、awsCliを使う


    • configはすでに設定してある




MFA = requiredはuserPool作成時しか設定できない

ドキュメントは以下

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-settings-mfa.html


必須以外なら変更できる

off <-> optional は可能。

スクリーンショットの通り。

cognito > MFA and verifications にて設定可能。

optionalにし、TOTPにチェックを入れておく。

cognito_ss_1.png

cognito_ss_2.png


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 のパラメータの記載が網羅されているものがあれば教えていただけないでしょうか...。

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-settings-mfa-totp.html

https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html


ちなみに

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();