Amazon CognitoのAdminDeleteSoftwareTokenを直接呼び出してTOTP設定をリセットしてみた

Amazon CognitoのAdminDeleteSoftwareTokenを直接呼び出してTOTP設定をリセットしてみた

mazon Cognitoに、ユーザーのTOTP MFA設定を管理者がリセットできるAdminDeleteSoftwareTokenが追加されました。AWS CLIとboto3は未対応でしたが、SigV4署名付きHTTPリクエストとして直接呼び出し、その動作を確認できました。
2026.08.27

はじめに

2026年8月26日、Amazon Cognitoに、管理者がユーザーのTOTP用ソフトウェアトークンを削除できるAdminDeleteSoftwareTokenが追加されました。TOTPデバイスを紛失したユーザーのトークンを削除し、MFAを再設定するためのAPIです。

https://aws.amazon.com/about-aws/whats-new/2026/08/amazon-cognito-totp-reset/

項目 AdminDeleteSoftwareToken追加前 追加後
管理者による対象ユーザーのTOTPリセット 既存のTOTPトークンを削除する専用の管理者APIはない AdminDeleteSoftwareToken で削除できる
MFA必須を維持したままの復旧 ユーザープール全体のMFA設定の変更、またはユーザーの削除・再作成を検討する必要がある 対象ユーザーのトークンを削除し、次回認証で返る MFA_SETUP から再設定フローを開始できる
影響範囲 ユーザープール全体、または対象ユーザーのID・関連データ 対象ユーザーのソフトウェアトークン

事前準備

検証はap-northeast-1で行いました。ユーザープールを作成したあと、ソフトウェアトークンMFAを有効にしてMFAを必須にし、パスワード認証用のアプリクライアントとダミーユーザーを用意しました。実際のIDやパスワードは掲載しないため、以下では変数を使用します。

MFA必須のユーザープール

まず、パスワード認証用のユーザープールを作成しました。

USER_POOL_ID=$(aws cognito-idp create-user-pool \
  --pool-name totp-reset-test-pool \
  --policies '{"PasswordPolicy":{"MinimumLength":8,"RequireUppercase":true,"RequireLowercase":true,"RequireNumbers":true,"RequireSymbols":false}}' \
  --query 'UserPool.Id' --output text)

ソフトウェアトークンMFAを有効にし、プールのMFAを必須にしました。

aws cognito-idp set-user-pool-mfa-config \
  --user-pool-id "$USER_POOL_ID" \
  --mfa-configuration ON \
  --software-token-mfa-configuration Enabled=true

アプリクライアントとダミーユーザー

パスワード認証を行うアプリクライアントを作成しました。

CLIENT_ID=$(aws cognito-idp create-user-pool-client \
  --user-pool-id "$USER_POOL_ID" \
  --client-name totp-test-client \
  --no-generate-secret \
  --explicit-auth-flows \
    ALLOW_ADMIN_USER_PASSWORD_AUTH \
    ALLOW_REFRESH_TOKEN_AUTH \
    ALLOW_USER_PASSWORD_AUTH \
  --query 'UserPoolClient.ClientId' --output text)

通知を送らないダミーユーザーを作成し、恒久パスワードを設定しました。

USERNAME=testuser
PASSWORD='<TestUserPassword>'

aws cognito-idp admin-create-user \
  --user-pool-id "$USER_POOL_ID" \
  --username "$USERNAME" \
  --temporary-password "$PASSWORD" \
  --message-action SUPPRESS

aws cognito-idp admin-set-user-password \
  --user-pool-id "$USER_POOL_ID" \
  --username "$USERNAME" \
  --password "$PASSWORD" \
  --permanent

ダミーユーザーはパスワード設定後にCONFIRMEDとなりました。認証したところMFA_SETUPチャレンジが返りました。

TOTP登録

恒久パスワードを設定したダミーユーザーに対し、MFA_SETUPのセッションを取得してTOTPを登録しました。

MFA_SETUP_SESSION="$(aws cognito-idp admin-initiate-auth \
  --user-pool-id "$USER_POOL_ID" \
  --client-id "$CLIENT_ID" \
  --auth-flow ADMIN_USER_PASSWORD_AUTH \
  --auth-parameters "USERNAME=$USERNAME,PASSWORD=$PASSWORD" \
  --query Session --output text)"

ASSOCIATE_JSON="$(aws cognito-idp associate-software-token \
  --session "$MFA_SETUP_SESSION" \
  --output json)"
TOTP_SECRET="$(printf '%s' "$ASSOCIATE_JSON" | \
  python3 -c 'import json,sys; print(json.load(sys.stdin)["SecretCode"])')"
ASSOCIATE_SESSION="$(printf '%s' "$ASSOCIATE_JSON" | \
  python3 -c 'import json,sys; print(json.load(sys.stdin)["Session"])')"

ローカル環境にoathtoolを導入せずに済むよう、Dockerコンテナ内のoathtoolでコードを生成しました。TOTP_SECRETと生成したコードは標準出力に表示しません。

TOTP_CODE="$(docker run --rm -e "TOTP_SECRET=$TOTP_SECRET" alpine sh -c \
  'apk add --no-cache oath-toolkit-oathtool >/dev/null && \
   oathtool --totp --base32 "$TOTP_SECRET"')"

aws cognito-idp verify-software-token \
  --session "$ASSOCIATE_SESSION" \
  --user-code "$TOTP_CODE" \
  --query Status --output text

SUCCESSが返ったあと、認証時にSOFTWARE_TOKEN_MFAチャレンジが返ることを確認しました。

API検証

事前準備でTOTPを登録したユーザーを対象に、削除前後で同じ項目を確認しました。

削除前の確認

認証要素

aws cognito-idp admin-get-user-auth-factors \
  --user-pool-id "$USER_POOL_ID" \
  --username "$USERNAME" \
  --query ConfiguredUserAuthFactors --output json
[
    "PASSWORD",
    "SOFTWARE_TOKEN"
]

認証時のチャレンジ

aws cognito-idp admin-initiate-auth \
  --user-pool-id "$USER_POOL_ID" \
  --client-id "$CLIENT_ID" \
  --auth-flow ADMIN_USER_PASSWORD_AUTH \
  --auth-parameters "USERNAME=$USERNAME,PASSWORD=$PASSWORD" \
  --query ChallengeName --output text
SOFTWARE_TOKEN_MFA

パスワードとソフトウェアトークンが認証要素に設定され、認証時にはTOTP用のチャレンジが返る状態です。

API実行

記事執筆時点で最新のAWS CLI 2.36.32とboto3 1.43.81は、AdminDeleteSoftwareTokenに未対応でした。

AWS CLIとboto3の代わりに、botocoreでSigV4署名を付与して直接呼び出しました。

import json
from urllib.request import Request, urlopen

from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest
from botocore.session import get_session

region = 'ap-northeast-1'
payload = {
    'UserPoolId': 'ap-northeast-1_XXXXXXXXX',
    'Username': 'testuser',
}
request = AWSRequest(
    method='POST',
    url=f'https://cognito-idp.{region}.amazonaws.com/',
    data=json.dumps(payload, separators=(',', ':')).encode(),
    headers={
        'Content-Type': 'application/x-amz-json-1.0',
        'X-Amz-Target': 'AWSCognitoIdentityProviderService.AdminDeleteSoftwareToken',
    },
)

credentials = get_session().get_credentials().get_frozen_credentials()
SigV4Auth(credentials, 'cognito-idp', region).add_auth(request)
prepared = request.prepare()
with urlopen(
    Request(prepared.url, data=prepared.body, headers=dict(prepared.headers.items()), method='POST')
) as response:
    print(f'HTTP {response.status}')
    print(response.read().decode() or '{}')

削除後の確認

AdminDeleteSoftwareTokenを実行したあと、削除前と同じコマンドで認証要素とパスワード認証時のチャレンジを確認しました。

認証要素

[
    "PASSWORD"
]

ソフトウェアトークンが削除され、認証要素はパスワードだけになりました。

認証時のチャレンジ

MFA_SETUP

次回認証では、新しいソフトウェアトークンを設定できるMFA_SETUPチャレンジが返りました。

まとめ

SMS MFAなどの代替要素がなく、TOTPだけをMFA要素として利用するユーザーでは、デバイス紛失時の復旧が課題でした。AdminDeleteSoftwareTokenを使えば、対象ユーザーのTOTPだけをリセットし、次回認証でMFA_SETUPに戻して再登録を促す復旧フローを実装できます。

TOTPデバイス紛失時の復旧を理由にCognitoのMFA必須化を見送っていた場合は、このフローを試してみてください。

今後は、公式SDKのサポートや、パスキーを含むTOTP以外の認証要素についても、管理者が対象ユーザー単位でリセットできるAPIが提供されることに期待したいところです。

参考リンク

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事