Skip to content

Count email otp reinitiation flow as resend flow#83

Open
PasinduYeshan wants to merge 1 commit into
wso2-extensions:mainfrom
PasinduYeshan:fix/6974
Open

Count email otp reinitiation flow as resend flow#83
PasinduYeshan wants to merge 1 commit into
wso2-extensions:mainfrom
PasinduYeshan:fix/6974

Conversation

@PasinduYeshan

@PasinduYeshan PasinduYeshan commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

This pull request enhances the Email OTP authenticator to treat implicit reinitiations (when an OTP is silently regenerated without explicit user action) as resend attempts, depending on a new configurable toggle. It also adds comprehensive tests to ensure the correct behavior for both enabled and disabled states of this feature.

Email OTP Resend Logic Improvements:

  • Added logic to detect implicit OTP reinitiation and, when the new CountReinitiationsAsResends toggle is enabled (defaulting to true), count these as resend attempts against the resend limit. This helps prevent abuse by limiting silent OTP regenerations. [1] [2] [3]
  • Introduced the SENT_OTP_TOKEN_TIME_PREFIX and COUNT_REINITIATIONS_AS_RESENDS constants to support the new logic. [1] [2]

Testing Enhancements:

  • Added unit tests to verify the toggle logic for counting implicit reinitiations as resends.
  • Added integration tests to ensure that implicit reinitiation correctly increments the resend counter when the toggle is on, and does not when the toggle is off.

Test Utility Updates:

  • Minor improvements to test imports for better argument matching.

Related PRs

Summary by CodeRabbit

  • New Features

    • Introduced a configurable setting (COUNT_REINITIATIONS_AS_RESENDS) to treat implicit OTP re-requests as resend attempts against rate limits, defaulting to enabled for improved abuse protection.
  • Tests

    • Added comprehensive test cases validating implicit OTP reinitiation behavior with the new configuration toggle in various scenarios.

@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 73.33333% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 53.31%. Comparing base (17ea79e) to head (e539671).

Files with missing lines Patch % Lines
...ity/local/auth/emailotp/EmailOTPAuthenticator.java 73.33% 0 Missing and 4 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main      #83      +/-   ##
============================================
+ Coverage     51.04%   53.31%   +2.26%     
+ Complexity      321      262      -59     
============================================
  Files            10       10              
  Lines          3111     3123      +12     
  Branches        943      951       +8     
============================================
+ Hits           1588     1665      +77     
+ Misses         1287     1227      -60     
+ Partials        236      231       -5     
Flag Coverage Δ
unit 51.08% <73.33%> (+9.28%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 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.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds logic to treat implicit OTP reinitiations (retry attempts that lack an entered code and RESEND flag while an OTP token already exists in context) as resend events under a new configurable toggle (COUNT_REINITIATIONS_AS_RESENDS). Two new constants, two private helper methods, and a refactored countAgainstResendLimit boolean unify resend-limit enforcement for both explicit resends and implicit reinitiations.

Changes

Implicit OTP Reinitiation Resend Accounting

Layer / File(s) Summary
New constants and detection helpers
...constant/AuthenticatorConstants.java, ...EmailOTPAuthenticator.java
Adds SENT_OTP_TOKEN_TIME_PREFIX and COUNT_REINITIATIONS_AS_RESENDS constants; introduces isImplicitOTPReinitation (detects retry without CODE/RESEND with token in context) and isCountReinitiationsAsResendsEnabled (reads runtime param, defaults to true).
Resend-limit enforcement refactor
...EmailOTPAuthenticator.java
Introduces countAgainstResendLimit boolean set for explicit RESEND_OTP and, when toggled, for implicit reinitiations; gates context resend-blocking check and both context/user-claim counter increments on this unified boolean rather than the previous RESEND_OTP-only condition.
Toggle unit tests and implicit reinit integration tests
...EmailOTPAuthenticatorTest.java, ...EmailOTPContextBasedRetryResendTest.java
Data-provider unit test for isCountReinitiationsAsResendsEnabled (empty/true/false optional); two integration tests asserting the context resend counter increments to 1 with toggle enabled and stays at 0 with toggle disabled.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hop, hop — the OTP flies once more,
But this time the counter knocks at the door.
A toggle decides if reinit counts as resend,
No sneaky re-trips 'round the limit's bend.
The tests all agree with a joyful "assert true!"
🥕 Another safe email — the rabbit approves you.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description covers the key technical changes, testing enhancements, and includes a related PR reference, but is missing several required sections from the template (Purpose with issue links, Release note, Documentation, Certification, and others). Add missing sections from the template: Purpose with issue links, Release note, Documentation link/explanation, Certification status, and Test environment details to provide complete context.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: treating email OTP reinitiation flows as resend flows, which accurately reflects the primary objective of the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@components/org.wso2.carbon.identity.local.auth.emailotp/src/main/java/org/wso2/carbon/identity/local/auth/emailotp/EmailOTPAuthenticator.java`:
- Around line 429-441: The resend count is being incremented and mutated before
confirming that sendEmailOtp() was successful. Move the mutations of
otpResendCount, shouldUpdateUserClaim, and the call to
updateContextOTPResendCount(context) to occur only after the sendEmailOtp() call
completes successfully. This ensures that failed OTP send attempts do not
consume the user's resend limit quota. The increment operations currently happen
before the email dispatch is confirmed, which can incorrectly block users when
sends fail.

In
`@components/org.wso2.carbon.identity.local.auth.emailotp/src/test/java/org/wso2/carbon/identity/local/auth/emailotp/EmailOTPContextBasedRetryResendTest.java`:
- Around line 335-338: The try-catch block in the method invocation is silently
ignoring InvocationTargetException, which can mask real test failures and cause
incorrect test results. Remove the empty catch block for
InvocationTargetException (around the method.invoke call for
emailOTPAuthenticator) and either let the exception propagate naturally or use a
proper assertion mechanism like assertThrows to validate expected exceptions.
This applies to all occurrences in the test class where
InvocationTargetException is being caught and ignored.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ac18cb83-fd65-49a6-844d-889a6d28df0c

📥 Commits

Reviewing files that changed from the base of the PR and between 17ea79e and e539671.

📒 Files selected for processing (4)
  • components/org.wso2.carbon.identity.local.auth.emailotp/src/main/java/org/wso2/carbon/identity/local/auth/emailotp/EmailOTPAuthenticator.java
  • components/org.wso2.carbon.identity.local.auth.emailotp/src/main/java/org/wso2/carbon/identity/local/auth/emailotp/constant/AuthenticatorConstants.java
  • components/org.wso2.carbon.identity.local.auth.emailotp/src/test/java/org/wso2/carbon/identity/local/auth/emailotp/EmailOTPAuthenticatorTest.java
  • components/org.wso2.carbon.identity.local.auth.emailotp/src/test/java/org/wso2/carbon/identity/local/auth/emailotp/EmailOTPContextBasedRetryResendTest.java

Comment on lines +335 to +338
try {
method.invoke(emailOTPAuthenticator, request, response, context);
} catch (InvocationTargetException ignored) {
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Don’t swallow invocation failures in these integration tests.

Ignoring InvocationTargetException can mask real failures; the toggle-off case can still pass with resend count staying at the pre-set 0.

✅ Suggested fix
-        try {
-            method.invoke(emailOTPAuthenticator, request, response, context);
-        } catch (InvocationTargetException ignored) {
-        }
+        try {
+            method.invoke(emailOTPAuthenticator, request, response, context);
+        } catch (InvocationTargetException e) {
+            Assert.fail("Unexpected exception from initiateAuthenticationRequest: " + e.getCause());
+        }

Also applies to: 405-408

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@components/org.wso2.carbon.identity.local.auth.emailotp/src/test/java/org/wso2/carbon/identity/local/auth/emailotp/EmailOTPContextBasedRetryResendTest.java`
around lines 335 - 338, The try-catch block in the method invocation is silently
ignoring InvocationTargetException, which can mask real test failures and cause
incorrect test results. Remove the empty catch block for
InvocationTargetException (around the method.invoke call for
emailOTPAuthenticator) and either let the exception propagate naturally or use a
proper assertion mechanism like assertThrows to validate expected exceptions.
This applies to all occurrences in the test class where
InvocationTargetException is being caught and ignored.

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.

1 participant