CognitoユーザープールのCLIでの認証

Cognitoユーザープール関連の検証をCLIでやるメモ。

参考リンク

ロールの作成

CognitoからSMSを送るのに必要なロールを作成する必要があり、その際にUUIDが必要なので生成する。

uuid=$(uuidgen | tr [:upper:] [:lower:])

ロールを作成する。ConditionにUUIDを含める。

cat <<EOF > trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "cognito-idp.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "${uuid}"
        }
      }
    }
  ]
}
EOF
aws iam create-role \
  --role-name MyUserPool-SMS-Role \
  --assume-role-policy-document file://trust-policy.json

管理ポリシーを作成する

cat <<EOF > policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sns:publish"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
EOF
aws iam create-policy \
  --policy-name Cognito-SNS-Policy \
  --policy-document file://policy.json
policy_arn=$(aws iam list-policies | jq -r '.Policies[] | select( .PolicyName == "Cognito-SNS-Policy" ) | .Arn')

管理ポリシーをロールにアタッチする。

aws iam attach-role-policy \
  --role-name MyUserPool-SMS-Role --policy-arn ${policy_arn}
role_arn=$(aws iam list-roles | jq -r '.Roles[] | select( .RoleName == "MyUserPool-SMS-Role" ) | .Arn')

ユーザープールの作成

電話番号の属性を必須にし、電話番号の確認とMFAを有効にしたユーザープールを作成する。

aws cognito-idp create-user-pool \
  --pool-name MyUserPool \
  --auto-verified-attributes phone_number \
  --sms-configuration SnsCallerArn=${role_arn},ExternalId=${uuid} \
  --mfa-configuration ON \
  --username-configuration CaseSensitive=false \
  --schema Name=phone_number,Required=true
user_pool_id=$(aws cognito-idp list-user-pools --max-results 10 | jq -r '.UserPools[] | select( .Name == "MyUserPool") | .Id')

アプリクライアントの作成

パスワード認証(ALLOW_USER_PASSWORD_AUTH)を使えるようにしてアプリクライアントを作成する。

aws cognito-idp create-user-pool-client \
  --user-pool-id ${user_pool_id} \
  --client-name MyUserPoolClient \
  --explicit-auth-flows "ALLOW_CUSTOM_AUTH" "ALLOW_REFRESH_TOKEN_AUTH" "ALLOW_USER_SRP_AUTH" "ALLOW_USER_PASSWORD_AUTH"
client_id=$(aws cognito-idp list-user-pool-clients --user-pool-id ${user_pool_id} | jq -r '.UserPoolClients[] | select( .ClientName == "MyUserPoolClient" ) | .ClientId')

サインアップ

ユーザーをサインアップする(これはIAMのクレデンシャルを使っていないコマンド)。

aws cognito-idp sign-up \
  --client-id ${client_id} \
  --username user1 \
  --password '<パスワード>' \
  --user-attributes Name="phone_number",Value="<電話番号>"
{
    "UserConfirmed": false,
    "CodeDeliveryDetails": {
        "Destination": "+********1234",
        "DeliveryMedium": "SMS",
        "AttributeName": "phone_number"
    },
    "UserSub": "1dda6cb7-e93d-4802-8419-a6bbaf7b0e7d"
}

ユーザーのステータスを確認する。UNCONFIRMEDのはず。

aws cognito-idp list-users --user-pool-id ${user_pool_id}

検証コードが届くので検証をする(これはIAMのクレデンシャルを使っていないコマンド)。

aws cognito-idp confirm-sign-up \
  --client-id ${client_id} \
  --username user1 \
  --confirmation-code <検証コード>

ユーザーのステータスを確認する。CONFIRMEDになっているはず。

aws cognito-idp list-users --user-pool-id ${user_pool_id}

ログイン

ログインする(これはIAMのクレデンシャルを使っていないコマンド)。

aws cognito-idp initiate-auth \
  --auth-flow USER_PASSWORD_AUTH \
  --client-id ${client_id} \
  --auth-parameters 'USERNAME=user1,PASSWORD=<パスワード>'

MFAチャレンジが返ってくる。

{
    "ChallengeName": "SMS_MFA",
    "Session": "<省略>",
    "ChallengeParameters": {
        "CODE_DELIVERY_DELIVERY_MEDIUM": "SMS",
        "CODE_DELIVERY_DESTINATION": "+********1234",
        "USER_ID_FOR_SRP": "user1"
    }
}

認証コードが送られてくるのでチャレンジを送る。

aws cognito-idp respond-to-auth-challenge \
  --client-id ${client_id} \
  --challenge-name SMS_MFA \
  --challenge-responses USERNAME=user1,SMS_MFA_CODE=<認証コード> \
  --session "<上記のSession>"

トークンが取得できた。

{
    "ChallengeParameters": {},
    "AuthenticationResult": {
        "AccessToken": "<省略>",
        "ExpiresIn": 3600,
        "TokenType": "Bearer",
        "RefreshToken": "<省略>",
        "IdToken": "<省略>"
    }
}