Skip to content

feat(cognito-idp): make TOTP MFA work#9785

Open
bdellegrazie wants to merge 3 commits intogetmoto:masterfrom
bdellegrazie:feat/cognito-totp
Open

feat(cognito-idp): make TOTP MFA work#9785
bdellegrazie wants to merge 3 commits intogetmoto:masterfrom
bdellegrazie:feat/cognito-totp

Conversation

@bdellegrazie
Copy link
Contributor

@bdellegrazie bdellegrazie commented Feb 25, 2026

Implement TOTP MFA using the existing cryptography API. This allows clients to behave correctly and use proper TOTP validation compared with previously where the UserCode was not handled.

Warning: this implementation still uses the fixed constant "secret" and therefore should not be considered for anything other than testing.

A solution implementing "real" TOTP was considered but would need storing the secret temporarily in the session during the auth process but the session object is unfortunately a tuple at this time.

Closes #9786

@bdellegrazie bdellegrazie force-pushed the feat/cognito-totp branch 2 times, most recently from 2acb0b8 to 6e1fb23 Compare February 25, 2026 15:22
@codecov
Copy link

codecov bot commented Feb 25, 2026

Codecov Report

❌ Patch coverage is 89.74359% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.11%. Comparing base (f58dc18) to head (62bd97f).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
moto/cognitoidp/models.py 83.33% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9785      +/-   ##
==========================================
- Coverage   93.11%   93.11%   -0.01%     
==========================================
  Files        1308     1308              
  Lines      118862   118896      +34     
==========================================
+ Hits       110683   110714      +31     
- Misses       8179     8182       +3     
Flag Coverage Δ
servertests 28.89% <43.58%> (+<0.01%) ⬆️
unittests 93.09% <89.74%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bdellegrazie bdellegrazie force-pushed the feat/cognito-totp branch 2 times, most recently from 04ee252 to 16859cf Compare February 26, 2026 11:45
@bdellegrazie
Copy link
Contributor Author

Added a test for the cognito_totp utility and rebased on master

Copy link
Collaborator

@bblommers bblommers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @bdellegrazie! I imagine that the majority of people will not go through the trouble of setting up TOTP in their tests, and will just use a random UserCode on verification. That is a valid test strategy, as far a I'm concerned.

I do see the benefit of this feature, though - can we hide it behind a feature flag? We typically use environment variables for these usecases, so in this case we could use: MOTO_COGNITO_ENABLE_TOTP=true.

Only if that env variable is set would Moto validate the provided UserCode - if not, Moto accepts everything.

I would also like to see a negative test: what happens when the user provides an invalid user code (with this env var enabled)? How does AWS behave when providing an invalid code?

@bdellegrazie bdellegrazie force-pushed the feat/cognito-totp branch 2 times, most recently from 348e15f to 12f041f Compare March 1, 2026 19:11
@bdellegrazie bdellegrazie requested a review from bblommers March 1, 2026 19:12
@bdellegrazie
Copy link
Contributor Author

bdellegrazie commented Mar 1, 2026

Hi @bblommers,

Thanks for the review!

  • I've used MOTO_COGNITO_IDP_USER_POOL_ENABLE_TOTP to match the existing Cognito feature flags, happy to change it if you would prefer.
  • Added negative test as requested
  • Added additional positive test when the feature is "masked" (i.e. not enabled) - this the same as the original _enabled test which has been converted to the real TOTP enabled test. I can change it to _disabled if you prefer but that may be confusing given TOTP is enabled, just it's verification is bypassed.
  • Fixed missing behaviour in respond_to_auth_challenge where the TOTP token wasn't being checked at all.
  • Made the totp secret a static constant (for the moment)

@bdellegrazie bdellegrazie force-pushed the feat/cognito-totp branch 4 times, most recently from 9496ca7 to 5b32839 Compare March 5, 2026 09:13
Implement TOTP MFA using the existing cryptography API.
This allows clients to behave correctly and use proper TOTP validation
compared with previously where the UserCode was not handled.

Warning: this implementation still uses the fixed constant "secret" and
therefore should not be considered for anything other than testing.

A solution implementing "real" TOTP was considered but would need
storing the secret temporarily in the session during the auth process
but the session object is unfortunately a tuple at this time.
* Put working TOTP MFA behind a feature flag - specifically
`MOTO_COGNITO_IDP_USER_POOL_ENABLE_TOTP`
* Support the FriendlyDeviceName field, although only for error
  reporting to end-user
@bdellegrazie
Copy link
Contributor Author

bdellegrazie commented Mar 9, 2026

@bblommers could you please re-review?

I had to delete the test which verifies the old behaviour (TOTP code of anything) because it doesn't work ServerSide.
If there's a marker which can exclude a test specifically on a server-side run, that would help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Cognito MFA TOTP support

2 participants