- OTP invalidation on resend is supported for native sign-up, SSPR, and strong authentication registration flows that use email OTP.
For sign-in, the documentation explicitly states:
“Microsoft Entra resends another one-time passcode if the previous one hasn't been verified. When Microsoft Entra resends a one-time passcode, it invalidates the previously sent code.”
For sign-up, SSPR, and strong auth registration, the same resend pattern is documented: to resend a one-time passcode, the app must call the corresponding .../challenge endpoint again, and the OTP value is then submitted via the .../continue (or .../submit) endpoint with grant_type=oob.
- The correct way to trigger resend (and thus invalidation of the previous OTP) is to call the appropriate
.../challenge endpoint again with the same continuation token and client ID, without calling .../start again:
- Sign-up:
- Resend OTP:
POST https://{tenant_subdomain}.ciamlogin.com/{tenant_subdomain}.onmicrosoft.com/signup/v1.0/challenge
- Required parameters include:
-
tenant_subdomain
-
client_id
-
continuation_token
-
challenge_type including oob (for email OTP)
- Then submit OTP:
POST /signup/v1.0/continue with:
-
grant_type=oob
-
oob={otp_code}
-
continuation_token
- SSPR:
- Resend OTP:
POST /resetpassword/v1.0/challenge again with:
-
tenant_subdomain
-
client_id
-
continuation_token
- Then submit OTP:
POST /resetpassword/v1.0/continue with:
-
grant_type=oob
-
oob={otp_code}
-
continuation_token
- Strong auth registration:
- Resend OTP:
POST /register/v1.0/challenge again
- Then submit OTP:
POST /register/v1.0/continue with:
-
grant_type=oob
-
oob={otp_code}
-
continuation_token
The documentation for these flows consistently states that to resend a one-time passcode, the app must call the relevant .../challenge endpoint again, and that the OTP is then submitted via the oob parameter to the .../continue or .../submit endpoint. For sign-in, it is explicitly stated that resending invalidates the previously sent code; the same resend mechanism is used for sign-up, SSPR, and registration.
- The provided documentation does not describe a platform limitation where both the old and new OTP remain valid simultaneously. It states that when a one-time passcode is resent (via the appropriate
.../challenge endpoint), the previously sent code is invalidated. It also documents the error behavior when an invalid OTP is submitted:
- For sign-up and SSPR, if the OTP is invalid, the
error is invalid_grant with suberror=invalid_oob_value.
- For SSPR,
invalid_request, invalid_grant, and expired_token are also documented, with invalid_oob_value indicating an invalid OTP.
If both old and new OTPs are accepted in the described flows even after a resend on the same continuation token, this behavior is not reflected in the documentation. In that case, the documented behavior (previous OTP invalidated on resend) should be considered the expected platform behavior, and the observed behavior would need to be investigated via a support channel.
References: