Add multi-device support for push authentication#10431
Add multi-device support for push authentication#10431raviendalpatadu wants to merge 10 commits into
Conversation
…guration management
- Introduced a new feature to allow users to register additional devices for push authentication, including UI updates in pushAuth.jsp. - Added internationalization support for new messages related to device registration and limits in Resources.properties and various translation files. - Implemented error handling for scenarios where the maximum device limit is reached in pushAuthError.jsp. - Updated the authentication provider settings to include options for enabling multiple device progressive enrollment with appropriate warnings. - Created a new SCSS file for styling nested settings in the push authenticator form.
…nd update translations
…s and improve back navigation logic
|
Warning Review limit reached
More reviews will be available in 54 minutes and 8 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (18)
📝 WalkthroughWalkthroughAdds push device management configuration end-to-end: a new ChangesPush Device Management End-to-End
Suggested reviewers
🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
…ch error in push authenticator
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #10431 +/- ##
==========================================
+ Coverage 72.62% 72.75% +0.12%
==========================================
Files 469 469
Lines 70633 70960 +327
Branches 240 240
==========================================
+ Hits 51300 51627 +327
Misses 19222 19222
Partials 111 111
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/myaccount/src/components/multi-factor-authentication/authenticators/push-authenticator.tsx (1)
99-105:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAvoid rendering an empty modal action bar during the QR step.
When
qrCodeis present, no action is returned, butModal.Actionsis still rendered. This leaves an empty footer area.Suggested fix
- { ( + { !qrCode && ( <Modal.Actions data-componentId={ `${ componentId }-view-modal-actions` } className ="actions" > { renderPushAuthenticatorWizardActions() } - </Modal.Actions>) - } + </Modal.Actions> + ) }Also applies to: 200-216
🤖 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 `@apps/myaccount/src/components/multi-factor-authentication/authenticators/push-authenticator.tsx` around lines 99 - 105, The Modal.Actions component is being rendered unconditionally even when renderPushAuthenticatorWizardActions() returns no content during the QR code step, resulting in an empty footer area. Modify the code to conditionally render the Modal.Actions wrapper only when renderPushAuthenticatorWizardActions() returns actual content. You can achieve this by storing the result of renderPushAuthenticatorWizardActions() in a variable first, then wrapping the entire Modal.Actions component in a conditional that checks if that result is not empty or null. Apply this fix wherever Modal.Actions is used with renderPushAuthenticatorWizardActions() throughout the file.
🧹 Nitpick comments (2)
apps/myaccount/src/components/multi-factor-authentication/authenticators/push-authenticator.tsx (1)
301-301: ⚡ Quick winUse
data-componentidfor new selector attributes.This newly-added selector uses
data-componentId; align it with the project’s selector convention to keep tests consistent.As per coding guidelines, "Use
data-componentidfor DOM element selection in tests ... Do not usedata-testid."🤖 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 `@apps/myaccount/src/components/multi-factor-authentication/authenticators/push-authenticator.tsx` at line 301, The selector attribute at line 301 uses `data-componentId` with camelCase, which does not align with the project's convention for test selector attributes. Change the attribute name from `data-componentId` to `data-componentid` (all lowercase) to maintain consistency with the project's coding guidelines for DOM element selection in tests.Source: Coding guidelines
apps/myaccount/src/hooks/use-push-authenticator.ts (1)
203-219: ⚡ Quick winAdd a named return interface for this custom hook.
The expanded return object is currently anonymous; a named return interface will keep call sites stable and self-documented.
As per coding guidelines, "Define a named return interface for custom hooks ... instead of using anonymous object types."
🤖 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 `@apps/myaccount/src/hooks/use-push-authenticator.ts` around lines 203 - 219, Create a named TypeScript interface for the return type of the usePushAuthenticator hook. Define an interface that includes all the properties currently being returned in the anonymous object: deleteRegisteredDevice, deviceLimit, handlePushAuthenticatorInitCancel, handlePushAuthenticatorSetupSubmit, initPushAuthenticatorRegFlow, isConfigPushAuthenticatorModalOpen, isDeviceLimitReached, isLoading, isPushDeviceMgtConfigLoading, isMultipleDeviceEnrollmentEnabled, isRegisteredDeviceListLoading, qrCode, registeredDeviceList, setIsConfigPushAuthenticatorModalOpen, and translateKey. Then apply this named interface as the explicit return type annotation for the usePushAuthenticator hook function.Source: Coding guidelines
🤖 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
`@apps/console/java/org.wso2.identity.apps.console.server.feature/resources/deployment.config.json.j2`:
- Around line 2847-2849: The `maxDeviceLimitUpperBound` property in the
`pushDeviceManagement` object is accessed without checking if the optional field
is defined, which can result in invalid JSON when the value is undefined. Wrap
the `maxDeviceLimitUpperBound` line with an `{% if
push_device_management.max_device_limit_upper_bound is defined %}` guard and
close it with `{% endif %}`, following the same conditional rendering pattern
used elsewhere in the template for optional fields like `routes`.
In `@apps/myaccount/src/hooks/use-push-authenticator.ts`:
- Around line 97-99: The maximumDeviceLimit parsing in the
PushAuthenticatorConstants.PROPERTY_MAXIMUM_DEVICE_LIMIT section uses parseInt
which can return NaN if the value is non-numeric or empty, causing
isDeviceLimitReached to behave unexpectedly. After parsing with parseInt,
validate that the result is a valid number using Number.isNaN() or isNaN(), and
if it is NaN, fall back to the default value of 1 instead of passing NaN
downstream. This ensures that invalid or missing preference values default to
the expected limit rather than bypassing device limit checks.
In `@apps/myaccount/src/models/push-authenticator.ts`:
- Around line 38-40: The interface ConfigPreferencePropertyInterface is exported
but unused, triggering a Knip linting error. Remove the export keyword from the
interface declaration so it becomes a local type only, preserving its use within
the file while eliminating the unused exported type warning.
In `@features/admin.identity-providers.v1/api/push-device-mgt-configs.ts`:
- Around line 57-63: The isLoading derivation in the return statement of the
hook at line 57 uses the formula !error && !data, which does not account for the
disabled fetch case. When shouldFetch is false, the requestConfig is null and
SWR does not run, leaving both data and error as undefined, causing isLoading to
evaluate to true indefinitely and block downstream logic in
push-authenticator-form.tsx. Fix the isLoading derivation to also check the
shouldFetch condition, so that when shouldFetch is false, isLoading is false to
allow the downstream useEffect to proceed properly.
In
`@features/admin.identity-providers.v1/components/forms/authenticators/push-authenticator-form.tsx`:
- Around line 241-242: Replace all instances of data-testid with
data-componentid throughout the push-authenticator-form component to comply with
project coding guidelines. Locate each occurrence where ["data-testid"] is used
(including the destructuring at line 241 and all other instances mentioned at
lines 676-677, 703-704, 787-788, 991-992, and 1016-1017) and change them to
["data-componentid"] to align with the IdentifiableComponentInterface pattern
required by the project.
In `@identity-apps-core/apps/authentication-portal/src/main/webapp/pushAuth.jsp`:
- Around line 334-339: The code retrieves and parses a stored timestamp from
sessionStorage using PUSH_AUTH_STORAGE_KEY, but does not validate that parseInt
returns a valid number. If the stored value is malformed, parseInt will return
NaN and cause invalid countdown logic. After parsing the stored value with
parseInt(stored, 10), add a validation check to ensure the result is not NaN. If
the parsed value is invalid, treat it the same as the else branch by setting
startedAt = Date.now() and updating sessionStorage with the fresh timestamp to
ensure valid state is always used for countdown calculations.
In
`@identity-apps-core/apps/authentication-portal/src/main/webapp/pushAuthError.jsp`:
- Around line 64-65: The i18n key error.push.max.device.limit.reached is defined
in the base English translation file Resources.properties but is missing from
all locale-specific variant files (de_DE, es_ES, fr_FR, ja_JP, nl_NL, pt_BR,
pt_PT, zh_CN). Add the error.push.max.device.limit.reached key with appropriate
translations to each of these locale-specific properties files to ensure
non-English users see translated error messages instead of the English fallback
when this error condition is triggered.
In `@modules/i18n/src/translations/pt-BR/portals/myaccount.ts`:
- Line 1030: The deviceLimitReachedHint translation string uses the plural form
"dispositivos" which reads awkwardly when limit equals 1. Update the string to
use pluralization-safe wording by either implementing proper i18n pluralization
rules if supported by the translation system (typically with separate singular
and plural variants), or by using neutral wording that works grammatically for
both singular and plural cases. Ensure the updated text reads naturally whether
the limit value is 1 or greater than 1.
In `@modules/i18n/src/translations/pt-PT/portals/myaccount.ts`:
- Line 1055: The deviceLimitReachedHint translation string uses plural form
"dispositivos" which reads awkwardly when limit equals 1 (e.g., "1 dispositivos"
is grammatically incorrect in Portuguese). Update the translation to use
pluralization-safe wording that works for both singular and plural cases, such
as using a neutral form like "dispositivo(s)" or restructuring the message to
avoid explicit plural agreement with the numeric variable, ensuring the text
reads naturally regardless of whether limit is 1 or greater than 1.
---
Outside diff comments:
In
`@apps/myaccount/src/components/multi-factor-authentication/authenticators/push-authenticator.tsx`:
- Around line 99-105: The Modal.Actions component is being rendered
unconditionally even when renderPushAuthenticatorWizardActions() returns no
content during the QR code step, resulting in an empty footer area. Modify the
code to conditionally render the Modal.Actions wrapper only when
renderPushAuthenticatorWizardActions() returns actual content. You can achieve
this by storing the result of renderPushAuthenticatorWizardActions() in a
variable first, then wrapping the entire Modal.Actions component in a
conditional that checks if that result is not empty or null. Apply this fix
wherever Modal.Actions is used with renderPushAuthenticatorWizardActions()
throughout the file.
---
Nitpick comments:
In
`@apps/myaccount/src/components/multi-factor-authentication/authenticators/push-authenticator.tsx`:
- Line 301: The selector attribute at line 301 uses `data-componentId` with
camelCase, which does not align with the project's convention for test selector
attributes. Change the attribute name from `data-componentId` to
`data-componentid` (all lowercase) to maintain consistency with the project's
coding guidelines for DOM element selection in tests.
In `@apps/myaccount/src/hooks/use-push-authenticator.ts`:
- Around line 203-219: Create a named TypeScript interface for the return type
of the usePushAuthenticator hook. Define an interface that includes all the
properties currently being returned in the anonymous object:
deleteRegisteredDevice, deviceLimit, handlePushAuthenticatorInitCancel,
handlePushAuthenticatorSetupSubmit, initPushAuthenticatorRegFlow,
isConfigPushAuthenticatorModalOpen, isDeviceLimitReached, isLoading,
isPushDeviceMgtConfigLoading, isMultipleDeviceEnrollmentEnabled,
isRegisteredDeviceListLoading, qrCode, registeredDeviceList,
setIsConfigPushAuthenticatorModalOpen, and translateKey. Then apply this named
interface as the explicit return type annotation for the usePushAuthenticator
hook function.
🪄 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: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 19a97ea1-75da-4210-9bd8-e7ba8542a194
📒 Files selected for processing (38)
apps/console/java/org.wso2.identity.apps.console.server.feature/resources/deployment.config.json.j2apps/console/src/public/deployment.config.jsonapps/myaccount/src/api/multi-factor-push.tsapps/myaccount/src/components/multi-factor-authentication/authenticators/push-authenticator.tsxapps/myaccount/src/configs/app.tsapps/myaccount/src/constants/mfa-constants.tsapps/myaccount/src/hooks/use-push-authenticator.tsapps/myaccount/src/models/app-config.tsapps/myaccount/src/models/push-authenticator.tsfeatures/admin.connections.v1/configs/endpoints.tsfeatures/admin.connections.v1/constants/connection-ui-constants.tsfeatures/admin.connections.v1/models/endpoints.tsfeatures/admin.core.v1/configs/app.tsfeatures/admin.core.v1/models/config.tsfeatures/admin.core.v1/store/reducers/config.tsfeatures/admin.identity-providers.v1/api/index.tsfeatures/admin.identity-providers.v1/api/push-device-mgt-configs.tsfeatures/admin.identity-providers.v1/components/forms/authenticators/push-authenticator-form.scssfeatures/admin.identity-providers.v1/components/forms/authenticators/push-authenticator-form.tsxfeatures/admin.identity-providers.v1/models/identity-provider.tsidentity-apps-core/apps/authentication-portal/src/main/resources/org/wso2/carbon/identity/application/authentication/endpoint/i18n/Resources.propertiesidentity-apps-core/apps/authentication-portal/src/main/webapp/pushAuth.jspidentity-apps-core/apps/authentication-portal/src/main/webapp/pushAuthError.jspidentity-apps-core/apps/authentication-portal/src/main/webapp/pushEnroll.jspmodules/i18n/src/models/namespaces/authentication-provider-ns.tsmodules/i18n/src/models/namespaces/myaccount-ns.tsmodules/i18n/src/translations/de-DE/portals/myaccount.tsmodules/i18n/src/translations/en-US/portals/authentication-provider.tsmodules/i18n/src/translations/en-US/portals/myaccount.tsmodules/i18n/src/translations/es-ES/portals/myaccount.tsmodules/i18n/src/translations/fr-FR/portals/myaccount.tsmodules/i18n/src/translations/ja-JP/portals/myaccount.tsmodules/i18n/src/translations/nl-NL/portals/myaccount.tsmodules/i18n/src/translations/pt-BR/portals/myaccount.tsmodules/i18n/src/translations/pt-PT/portals/myaccount.tsmodules/i18n/src/translations/si-LK/portals/myaccount.tsmodules/i18n/src/translations/ta-IN/portals/myaccount.tsmodules/i18n/src/translations/zh-CN/portals/myaccount.ts
…ing and improve code formatting
…ling, update component IDs, and improve internationalization strings
d1e72ad to
b8255eb
Compare
This pull request introduces support for configurable device limits in the Push Authenticator feature, enabling dynamic control over how many devices a user can register for push-based multi-factor authentication. The changes span backend configuration, frontend API integration, UI logic, and new constants/models to support this feature.
Push Device Management Configuration Support
maxDeviceLimitUpperBound, to deployment configuration files (deployment.config.json.j2,deployment.config.json).pushDeviceMgtConfigsendpoint for fetching device management preferences.Frontend API and State Management Enhancements
Implemented a new API method
getConfigPreferencesto fetch push device management preferences from the backend, and introduced related TypeScript interfaces for request/response modeling.Added a React hook (
usePushAuthenticator) that loads device management config, exposes device limit state, and disables device enrollment when the limit is reached.UI/UX Improvements for Device Enrollment
Updated the Push Authenticator component to:
Constants and Validation
These changes collectively provide a robust, configurable, and user-friendly way to manage the number of devices a user can register for push-based MFA, with clear feedback and enforcement in the UI.
Related Issues