Skip to content

Introduce the device registration component#8207

Open
kaviska wants to merge 4 commits into
wso2:masterfrom
kaviska:device-reg
Open

Introduce the device registration component#8207
kaviska wants to merge 4 commits into
wso2:masterfrom
kaviska:device-reg

Conversation

@kaviska

@kaviska kaviska commented Jul 16, 2026

Copy link
Copy Markdown

Proposed changes in this pull request

This PR introduces the org.wso2.carbon.identity.device.registration component, which handles device registration as a flow executor. It implements a two-phase ECDSA challenge-response handshake to verify that a device owns the private key corresponding to the public key it is registering.

The registration flow works as follows:

  1. Initiate – The executor generates a random challenge and a registrationId, then requests the device's publicKey and signature.
  2. Client-side – The device signs the challenge using its private key.
  3. Verify – The executor validates the signature against the stored challenge. If a policyName is configured, it also evaluates the device against the configured device policy.
  4. Persist – Once the overall flow reaches STATUS_COMPLETE, the verified device is associated with the authenticated user and persisted through DeviceManagementService.persistDevice(...).

Persistence is intentionally handled outside the executor. During flows such as user registration, the user record may not exist when the device registration step executes, so the device cannot be persisted until the flow completes successfully.

This component includes

  • DeviceRegistrationExecutor – Implements the two-phase registration protocol as an Executor OSGi service. It also supports an optional policyName executor metadata property to enforce device policy validation during registration.
  • RegistrationFlowCompletionListener – Persists the verified device after successful flow completion, regardless of flow type. Since persistence happens only after the flow completes successfully, there is no need for rollback logic if a later step fails.
  • VerifiedDevice – Represents a device whose ownership has been verified but has not yet been associated with a user. It can only be converted into a persistable Device through bindTo(userId), ensuring that only user-bound devices can be stored.
  • DeviceRegistrationException – A module-specific checked exception with CLIENT and SERVER error types, following the same pattern used by other identity framework components.
  • Challenge management – The registration challenge is stored in the flow's FlowExecutionContext for the lifetime of the handshake. After a successful verification, the challenge is removed to prevent reuse. If verification fails, it is retained so the client can retry.

Usage

DeviceRegistrationExecutor is registered as an Executor OSGi service. The flow engine discovers it automatically and makes it available to any flow definition that references DeviceRegistrationExecutor in an EXECUTION step.

Integration with other components

This component builds on existing device management and policy components rather than duplicating their responsibilities.

  • device.mgt – Responsible for device persistence and lifecycle management. This component persists devices through DeviceManagementService.persistDevice(...).
  • device.policy – Responsible for device compliance evaluation. When a policyName is configured, the executor invokes DevicePolicyEvaluator.evaluate(...) before the device is persisted.

Testing

Unit tests cover:

  • Challenge generation
  • Signature verification (valid, tampered, incorrect key, and malformed key scenarios)
  • Single-use challenge enforcement
  • Executor phase transitions and error handling
  • Device persistence after flow completion across different flow types
  • Exception handling utilities

When should this PR be merged

This component depends on:

  • org.wso2.carbon.identity.device.mgt
  • org.wso2.carbon.identity.device.policy
  • org.wso2.carbon.identity.policy.management
  • org.wso2.carbon.identity.policy.evaluation

Follow up actions

N/A

kaviska added 3 commits July 12, 2026 20:38
Introduce org.wso2.carbon.identity.device.registration, which implements the
device registration challenge-response protocol and the registration flow
executor.

Wire the module into the build via a new components/device-mgt aggregator and
the root pom. The module depends on org.wso2.carbon.identity.device.policy,
org.wso2.carbon.identity.policy.management and
org.wso2.carbon.identity.policy.evaluation, which are not yet on master, so it
will compile once those modules land.
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: b68eaabc-4675-4f6f-ab16-071510f93374

📥 Commits

Reviewing files that changed from the base of the PR and between 29b7c32 and 593f118.

📒 Files selected for processing (4)
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutor.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/handler/DeviceRegistrationHandler.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/model/VerifiedDevice.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutorTest.java
🚧 Files skipped from review as they are similar to previous changes (4)
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/model/VerifiedDevice.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutorTest.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutor.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/handler/DeviceRegistrationHandler.java

📝 Walkthrough

Walkthrough

Changes

Adds a device registration bundle with challenge-response verification, optional device policy evaluation, deferred persistence through a flow listener, OSGi service wiring, Maven integration, and TestNG and runtime configuration.

Device registration

Layer / File(s) Summary
Build and module integration
pom.xml, components/device-mgt/pom.xml, components/device-mgt/org.wso2.carbon.identity.device.registration/pom.xml
Adds the device-management reactor module and configures the registration OSGi bundle, dependencies, TestNG execution, and SpotBugs analysis.
Registration protocol and data contracts
components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/{internal/{constant,exception,handler,model,util},model}/...
Adds challenge generation, ECDSA signature verification, structured exceptions, registration models, and conversion of verified devices into persistable devices.
Executor phases and policy evaluation
components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutor.java
Implements initiation and completion phases, flow-context challenge handling, device-data requirements, policy evaluation, response mapping, and no-op rollback.
OSGi wiring and deferred persistence
components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/{internal/component,listener}/..., .../internal/util/DeviceRegistrationDiagnosticLogger.java
Registers the executor and completion listener, injects device services, persists verified devices after completion, and emits diagnostic events.
Validation and test runtime configuration
components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/...
Adds tests for protocol handling, signature verification, executor responses, exception formatting, listener persistence, and Carbon/TestNG runtime configuration.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description summarizes the feature, but it does not follow the required template or include most required sections. Rewrite it using the template headings and add Purpose, Goals, Approach, User stories, Release note, Documentation, Automation tests, Security checks, and the remaining required sections.
Docstring Coverage ⚠️ Warning Docstring coverage is 31.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding the device registration component.
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.
✨ 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.

@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (2)
components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutorTest.java (2)

115-174: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the public TestNG lifecycle methods.

setUpClass, tearDownClass, setUp, and tearDownMethod are public but undocumented. The repository’s test exemption applies to methods annotated with @Test, not lifecycle methods.

As per coding guidelines, “All public methods should have a docstring.” Based on learnings, public test methods annotated with Test can be exempt from Javadoc requirements.

🤖 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/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutorTest.java`
around lines 115 - 174, Add Javadoc documentation to the public TestNG lifecycle
methods setUpClass, tearDownClass, setUp, and tearDownMethod in
DeviceRegistrationExecutorTest. Keep the documentation concise and describe each
method’s setup or cleanup responsibility without changing lifecycle behavior.

Sources: Coding guidelines, Learnings


561-566: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Match the security-critical verification inputs explicitly.

Using any() for every argument allows these tests to pass if the executor forwards the wrong registration ID, challenge, public key, or signature.

Proposed tightening
 mocked.when(() -> DeviceRegistrationHandler.verify(
-        any(), any(), any(), any(), any(), any(), any()))
+        eq(REGISTRATION_ID),
+        eq(CHALLENGE),
+        eq("base64PublicKey"),
+        eq("base64Signature"),
+        any(), any(), any()))
         .thenReturn(device);
🤖 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/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutorTest.java`
around lines 561 - 566, Update mockVerifySuccess to stub
DeviceRegistrationHandler.verify with the exact verification inputs expected by
each test—especially registration ID, challenge, public key, and
signature—instead of any() matchers. Pass or expose those expected values
through the helper as needed while preserving the returned VerifiedDevice.
🤖 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/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutor.java`:
- Around line 221-239: Update the failure handling around the challenge removal
in DeviceRegistrationExecutor so policy validation failures do not leave a
registration context with its challenge absent. When device-data validation or
evaluatePolicy returns an error, clear the remaining registration context and
issue a new challenge before returning, while preserving successful single-use
challenge consumption.
- Around line 141-144: Remove the setUsername call on the thread-local Carbon
context in the DeviceRegistrationExecutor flow before
DeviceRegistrationHandler.initiate; pass the existing username directly as
already done, without modifying pooled-thread context state.

In
`@components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/handler/DeviceRegistrationHandler.java`:
- Around line 75-79: Update the debug log in DeviceRegistrationHandler to remove
the raw username from the “Device registration initiated” message. Retain only
the tenantDomain and registrationId, or apply the project’s established
username-masking utility if one exists.

In
`@components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/model/VerifiedDevice.java`:
- Around line 48-55: Update the VerifiedDevice constructor to defensively copy
builder.registeredAt rather than storing the mutable Timestamp reference
directly. Also ensure the class’s getter and any reuse or builder paths return
or retain independent Timestamp copies, preserving the registration time from
external mutation.

In
`@components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutorTest.java`:
- Around line 413-435: Extend
testExecuteCompletionPolicyConfiguredButNoDeviceDataReturnsDeviceDataRequiredError
to retry the same flow with FIELD_DEVICE_DATA restored and assert successful
completion. In DeviceRegistrationExecutor.execute, preserve CTX_CHALLENGE when
FIELD_DEVICE_DATA is missing or policy validation fails, and remove it only
after successful device-data and policy validation so the corrected retry can
verify successfully.

---

Nitpick comments:
In
`@components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutorTest.java`:
- Around line 115-174: Add Javadoc documentation to the public TestNG lifecycle
methods setUpClass, tearDownClass, setUp, and tearDownMethod in
DeviceRegistrationExecutorTest. Keep the documentation concise and describe each
method’s setup or cleanup responsibility without changing lifecycle behavior.
- Around line 561-566: Update mockVerifySuccess to stub
DeviceRegistrationHandler.verify with the exact verification inputs expected by
each test—especially registration ID, challenge, public key, and
signature—instead of any() matchers. Pass or expose those expected values
through the helper as needed while preserving the returned VerifiedDevice.
🪄 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: 355fafe9-dabc-477c-aded-7f462e5680d4

📥 Commits

Reviewing files that changed from the base of the PR and between de88dd0 and 29b7c32.

📒 Files selected for processing (24)
  • components/device-mgt/org.wso2.carbon.identity.device.registration/pom.xml
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutor.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/component/DeviceRegistrationComponentServiceHolder.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/component/DeviceRegistrationServiceComponent.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/constant/DeviceRegistrationConstants.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/constant/ErrorMessage.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/exception/DeviceRegistrationException.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/handler/DeviceRegistrationHandler.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/model/DeviceRegistrationChallenge.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/util/DeviceRegistrationDiagnosticLogger.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/util/DeviceRegistrationExceptionHandler.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/internal/util/DeviceSignatureVerifier.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/listener/RegistrationFlowCompletionListener.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/main/java/org/wso2/carbon/identity/device/registration/model/VerifiedDevice.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/executor/DeviceRegistrationExecutorTest.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/internal/handler/DeviceRegistrationHandlerTest.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/internal/util/DeviceRegistrationExceptionHandlerTest.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/internal/util/DeviceSignatureVerifierTest.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/java/org/wso2/carbon/identity/device/registration/listener/RegistrationFlowCompletionListenerTest.java
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/resources/repository/conf/carbon.xml
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/resources/repository/conf/identity/identity.xml
  • components/device-mgt/org.wso2.carbon.identity.device.registration/src/test/resources/testng.xml
  • components/device-mgt/pom.xml
  • pom.xml

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