Skip to content

Add integration tests for shared user direct login - #27798

Closed
Yasasr1 wants to merge 1 commit into
wso2:masterfrom
Yasasr1:shared-user-integration
Closed

Add integration tests for shared user direct login#27798
Yasasr1 wants to merge 1 commit into
wso2:masterfrom
Yasasr1:shared-user-integration

Conversation

@Yasasr1

@Yasasr1 Yasasr1 commented May 14, 2026

Copy link
Copy Markdown
Contributor

$subject

@jenkins-is-staging

Copy link
Copy Markdown
Contributor

PR builder started
Link: https://github.com/wso2/product-is/actions/runs/25848494537

@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary

This PR adds comprehensive integration tests for shared user authentication flows across different organizational scenarios in WSO2 Identity Server. The tests validate OAuth2/OIDC login mechanisms when applications and users are shared between root organizations and sub-organizations.

Changes

New Test Classes:

  1. SharedUserLegacyOrgAuthenticationTestCase - Tests an OAuth2/OIDC flow for legacy organization authentication where an application and user are shared from a root organization to a sub-organization. The test covers application creation, organization setup, application sharing, user sharing, authorization flow discovery, and token validation.

  2. SharedUserSubOrgApplicationAuthenticationTestCase - Validates OAuth2 authorization-code authentication against a sub-organization application when the user originates from the root organization. Tests include sub-org creation, application setup, user provisioning, and token verification.

  3. SharedUserSubOrgAppFederatedAssociationTestCase - Tests a federated authentication flow across two Identity Server instances, covering sub-organization creation, federated identity provider setup, user provisioning, federated association creation, and federated login with token validation.

Configuration & Resource Updates:

  • shared-user-federation-authorized-apis.json - Updated test resource configuration to include API authorization scopes for organization management, applications, API resources, user management, and identity providers.

  • testng.xml - Updated test suite configuration to register the new test classes in both the default and federation-restart test suites.

Test Coverage

All three test classes validate that the sub claim in the returned ID token correctly references the root organization user ID, ensuring shared user identity is properly preserved through the authentication flows.

Walkthrough

This PR introduces three new TestNG integration test classes validating OAuth2/OIDC authentication for shared users across organization hierarchies in WSO2 Identity Server. The tests cover three distinct scenarios: legacy organization authentication (users and apps shared to sub-orgs), direct sub-organization application authentication (users shared to sub-orgs), and federated authentication (shared users with external identity providers across two IS instances). Each test orchestrates a complete flow from provisioning orgs, applications, and users through authentication and token verification. Supporting changes include API authorization configuration for management endpoints and test suite registration.

Sequence Diagram

sequenceDiagram
  participant User as Shared User<br/>(Root Org)
  participant RootOrg as Root<br/>Organization
  participant SubOrg as Sub-<br/>Organization
  participant App as OAuth2<br/>Application
  participant IdP as External<br/>IdP (Federated)
  
  Note over User,IdP: Legacy & Sub-Org Scenarios
  User->>SubOrg: Authenticate via SharedUserIdentifierExecutor
  SubOrg->>App: Authorization request
  SubOrg->>SubOrg: Resolve shared user from root org
  App->>User: Issue id_token with sub claim as root user ID
  
  Note over User,IdP: Federated Scenario
  User->>SubOrg: Authorize to sub-org app
  SubOrg->>IdP: Redirect to federated IdP
  IdP->>IdP: Authenticate user
  IdP->>SubOrg: Return assertion/token
  SubOrg->>SubOrg: Create federated association
  SubOrg->>SubOrg: Map to shared root user
  App->>User: Issue id_token with sub claim as root user ID
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changeset: three new integration test classes for shared user authentication scenarios across different organizational configurations.
Description check ✅ Passed The description is minimal but directly related to the changeset, confirming the addition of integration tests for shared user direct login functionality.
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 and usage tips.

@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: 3

🧹 Nitpick comments (7)
modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgAppFederatedAssociationTestCase.java (5)

460-465: 💤 Low value

Specify charset explicitly when encoding the Basic auth credentials.

(subOrgClientId + ":" + subOrgClientSecret).getBytes() relies on the platform default charset. Use StandardCharsets.UTF_8 (or ISO_8859_1 per RFC 7617) to make the encoding deterministic across environments.

🔧 Proposed fix
-        headers.add(new BasicHeader("Authorization", "Basic " +
-                Base64.encodeBase64String((subOrgClientId + ":" + subOrgClientSecret).getBytes()).trim()));
+        headers.add(new BasicHeader("Authorization", "Basic " +
+                Base64.encodeBase64String((subOrgClientId + ":" + subOrgClientSecret)
+                        .getBytes(java.nio.charset.StandardCharsets.UTF_8)).trim()));
🤖 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
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgAppFederatedAssociationTestCase.java`
around lines 460 - 465, The Basic auth credential encoding uses platform-default
bytes; update the Base64.encodeBase64String call that builds the "Authorization"
header (where headers is populated with new BasicHeader("Authorization", "Basic
" + Base64.encodeBase64String((subOrgClientId + ":" +
subOrgClientSecret).getBytes()).trim())) to supply an explicit charset, e.g. use
(subOrgClientId + ":" + subOrgClientSecret).getBytes(StandardCharsets.UTF_8) or
StandardCharsets.ISO_8859_1 per RFC 7617 so the encoding is deterministic across
environments.

579-579: 💤 Low value

Pass an explicit charset (and consider building the JSON safely) when constructing request bodies.

Both createIdpInSubOrg and createFederatedAssociationInSubOrg build a StringEntity without specifying the charset, and the latter also assembles JSON via string concatenation. Switching to new StringEntity(body, StandardCharsets.UTF_8) (or ContentType.APPLICATION_JSON) makes the content-type/charset explicit, and serializing via JSONObject/Gson avoids subtle escaping issues if the inputs ever change.

Also applies to: 600-607

🤖 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
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgAppFederatedAssociationTestCase.java`
at line 579, The StringEntity usage in createIdpInSubOrg and
createFederatedAssociationInSubOrg currently omits an explicit charset and the
latter builds JSON via string concatenation; update both places to construct the
entity with an explicit charset or content type (e.g., use new
StringEntity(body, StandardCharsets.UTF_8) or StringEntity(body,
ContentType.APPLICATION_JSON)) and stop hand-concatenating JSON—serialize
request payloads using a JSON library (e.g., JSONObject/Gson) to build
jsonRequest safely before wrapping it in the StringEntity so
content-type/charset and escaping are correct.

145-149: ⚡ Quick win

Derive secondary-IS URLs from DEFAULT_PORT + PORT_OFFSET_1 instead of hardcoding 9853/9854.

getSecondaryISURI() correctly computes the host as DEFAULT_PORT + PORT_OFFSET_1, but PRIMARY_IS_CALLBACK_URL, SECONDARY_IS_AUTHORIZE_ENDPOINT, SECONDARY_IS_TOKEN_ENDPOINT, SECONDARY_IS_LOGOUT_ENDPOINT, and SECONDARY_IS_COMMONAUTH_URL hardcode the port numbers. If DEFAULT_PORT changes or the framework remaps offsets, these constants will silently drift and the federated IdP will point at the wrong instance.

Consider building these URLs in testInit() (or via a helper) using the same offset arithmetic so all endpoints stay consistent.

🤖 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
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgAppFederatedAssociationTestCase.java`
around lines 145 - 149, The constants PRIMARY_IS_CALLBACK_URL,
SECONDARY_IS_AUTHORIZE_ENDPOINT, SECONDARY_IS_TOKEN_ENDPOINT,
SECONDARY_IS_LOGOUT_ENDPOINT, and SECONDARY_IS_COMMONAUTH_URL are hardcoded to
ports 9853/9854 and can drift; instead compute these URLs using the same port
arithmetic used by getSecondaryISURI() (i.e., DEFAULT_PORT + PORT_OFFSET_1) —
move their initialization into testInit() or a helper so you build each endpoint
by concatenating the computed base URI from getSecondaryISURI() (or a new
getSecondaryBase()) with the respective path (/commonauth, /oauth2/authorize,
/oauth2/token, /oidc/logout), ensuring all references use the computed fields
rather than hardcoded strings.

179-182: 💤 Low value

Empty factory constructor with unused userMode parameter.

The constructor accepts TestUserMode but does not use it. The data provider supplies only SUPER_TENANT_ADMIN, and the parent's initTest() method does not require user-mode-driven initialization. Consider removing the unused parameter and the configProvider data provider to clarify that this test runs in a single configuration, not multiple parameterized variants.

🤖 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
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgAppFederatedAssociationTestCase.java`
around lines 179 - 182, The constructor
SharedUserSubOrgAppFederatedAssociationTestCase currently annotated with
`@Factory` and accepting an unused TestUserMode parameter should be simplified:
remove the TestUserMode parameter from the constructor and remove the
`@Factory`(dataProvider = "configProvider") usage (and the corresponding
configProvider data provider method) so the test is no longer parameterized;
update or remove any imports related to TestUserMode and the data provider to
avoid unused imports and ensure the test runs as a single-configuration case.

569-591: ⚡ Quick win

Reuse the configured test HTTP client instead of creating fresh HttpClients.createDefault() instances for these organization-scoped HTTPS calls.

The createIdpInSubOrg and createFederatedAssociationInSubOrg methods create fresh HTTP clients to call organization-scoped endpoints at https://localhost:<offset>/o/api/.... The default client lacks the test environment configuration. The class already provides a properly configured createHttpClient() method (initialized at line 195 as the client field) that handles cookie specifications and redirect strategies appropriate for the test context. Additionally, the two methods duplicate identical HTTP client setup logic.

Consider using the configured client instance for both calls, or refactor the bearer token authentication into a reusable helper method to eliminate duplication.

🤖 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
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgAppFederatedAssociationTestCase.java`
around lines 569 - 591, The methods createIdpInSubOrg and
createFederatedAssociationInSubOrg currently instantiate a fresh HttpClient
(HttpClients.createDefault()) and duplicate request setup; replace those fresh
clients with the already-configured test client created by createHttpClient()
(the class-level client field) and remove the duplicate client creation logic,
and refactor the shared header/entity setup (Authorization: Bearer
switchedM2MToken, Content-Type: application/json, User-Agent) into a small
helper used by both methods to prepare HttpPost requests; ensure you still close
responses but do not close the shared client.
modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserLegacyOrgAuthenticationTestCase.java (2)

217-220: ⚡ Quick win

Read back the authentication sequence after patching.

updateSubOrgApplication(...) is the only step that installs SharedUserIdentifierExecutor. If that patch is ignored or partially applied, the failure only shows up much later in the login flow. A read-back assertion here would keep the failure localized to setup.

🤖 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
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserLegacyOrgAuthenticationTestCase.java`
around lines 217 - 220, After calling
oAuth2RestClient.updateSubOrgApplication(sharedAppId, patchModel,
switchedM2MToken) you must read back the patched application and assert the
authentication sequence was applied (so issues installing
SharedUserIdentifierExecutor are caught early); call the corresponding getter
(e.g., oAuth2RestClient.getSubOrgApplication or equivalent) for sharedAppId
using switchedM2MToken, retrieve the authentication sequence from the returned
Application model, and assert it contains the SharedUserIdentifierExecutor (or
matches the authSequence you set via
ApplicationPatchModel.setAuthenticationSequence) so the test fails at setup if
the patch wasn't applied.

359-366: ⚡ Quick win

Assert the token response status before parsing JSON.

A non-success token response will currently surface as a parsing or missing-field failure. Checking the HTTP status first will make OAuth flow failures much easier to diagnose.

🤖 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
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserLegacyOrgAuthenticationTestCase.java`
around lines 359 - 366, Before parsing the token response, assert the HTTP
status code on the HttpResponse (response) returned by sendPostRequest to ensure
the token endpoint (ACCESS_TOKEN_ENDPOINT via getTenantQualifiedURL) succeeded;
check response.getStatusLine().getStatusCode() (or equivalent) equals 200 and
fail with a clear message if not, so you don't attempt to parse
responseBody/jsonResponse when the endpoint returned an error.
🤖 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
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserLegacyOrgAuthenticationTestCase.java`:
- Around line 243-247: The SCIM filter string built in
SharedUserLegacyOrgAuthenticationTestCase (variable userSearchReq) is missing
quotes around the username; update the "filter" value to quote the string
literal (e.g., construct the filter as "userName eq \"<USERNAME>\"" using
ROOT_USER_USERNAME) so the SearchRequest conforms to SCIM 2.0 string literal
rules.

In
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgAppFederatedAssociationTestCase.java`:
- Around line 350-354: The SCIM filter string in the userSearchReq JSON is
missing quotes around the comparison value; update the filter construction in
SharedUserSubOrgAppFederatedAssociationTestCase where userSearchReq is built so
the filter uses quoted string syntax per RFC 7644 (i.e., produce userName eq
"ROOT_USER_USERNAME" with proper escaping), ensuring the
JSONObject.put("filter", ...) uses the quoted form and still references the
ROOT_USER_USERNAME constant.

In
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgApplicationAuthenticationTestCase.java`:
- Around line 227-234: The SCIM filter string built for userSearchReq is missing
quotes around the username value; update the filter to use the SCIM-compliant
format userName eq "<value>" (e.g., wrap ROOT_USER_USERNAME in quotes or use the
existing helper like OutboundProvisioningTestUtils.buildEncodedUserNameFilter())
before calling scim2RestClient.isSharedUserCreationCompleted so the filter
becomes quoted and properly encoded for SCIM 2.0.

---

Nitpick comments:
In
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserLegacyOrgAuthenticationTestCase.java`:
- Around line 217-220: After calling
oAuth2RestClient.updateSubOrgApplication(sharedAppId, patchModel,
switchedM2MToken) you must read back the patched application and assert the
authentication sequence was applied (so issues installing
SharedUserIdentifierExecutor are caught early); call the corresponding getter
(e.g., oAuth2RestClient.getSubOrgApplication or equivalent) for sharedAppId
using switchedM2MToken, retrieve the authentication sequence from the returned
Application model, and assert it contains the SharedUserIdentifierExecutor (or
matches the authSequence you set via
ApplicationPatchModel.setAuthenticationSequence) so the test fails at setup if
the patch wasn't applied.
- Around line 359-366: Before parsing the token response, assert the HTTP status
code on the HttpResponse (response) returned by sendPostRequest to ensure the
token endpoint (ACCESS_TOKEN_ENDPOINT via getTenantQualifiedURL) succeeded;
check response.getStatusLine().getStatusCode() (or equivalent) equals 200 and
fail with a clear message if not, so you don't attempt to parse
responseBody/jsonResponse when the endpoint returned an error.

In
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgAppFederatedAssociationTestCase.java`:
- Around line 460-465: The Basic auth credential encoding uses platform-default
bytes; update the Base64.encodeBase64String call that builds the "Authorization"
header (where headers is populated with new BasicHeader("Authorization", "Basic
" + Base64.encodeBase64String((subOrgClientId + ":" +
subOrgClientSecret).getBytes()).trim())) to supply an explicit charset, e.g. use
(subOrgClientId + ":" + subOrgClientSecret).getBytes(StandardCharsets.UTF_8) or
StandardCharsets.ISO_8859_1 per RFC 7617 so the encoding is deterministic across
environments.
- Line 579: The StringEntity usage in createIdpInSubOrg and
createFederatedAssociationInSubOrg currently omits an explicit charset and the
latter builds JSON via string concatenation; update both places to construct the
entity with an explicit charset or content type (e.g., use new
StringEntity(body, StandardCharsets.UTF_8) or StringEntity(body,
ContentType.APPLICATION_JSON)) and stop hand-concatenating JSON—serialize
request payloads using a JSON library (e.g., JSONObject/Gson) to build
jsonRequest safely before wrapping it in the StringEntity so
content-type/charset and escaping are correct.
- Around line 145-149: The constants PRIMARY_IS_CALLBACK_URL,
SECONDARY_IS_AUTHORIZE_ENDPOINT, SECONDARY_IS_TOKEN_ENDPOINT,
SECONDARY_IS_LOGOUT_ENDPOINT, and SECONDARY_IS_COMMONAUTH_URL are hardcoded to
ports 9853/9854 and can drift; instead compute these URLs using the same port
arithmetic used by getSecondaryISURI() (i.e., DEFAULT_PORT + PORT_OFFSET_1) —
move their initialization into testInit() or a helper so you build each endpoint
by concatenating the computed base URI from getSecondaryISURI() (or a new
getSecondaryBase()) with the respective path (/commonauth, /oauth2/authorize,
/oauth2/token, /oidc/logout), ensuring all references use the computed fields
rather than hardcoded strings.
- Around line 179-182: The constructor
SharedUserSubOrgAppFederatedAssociationTestCase currently annotated with
`@Factory` and accepting an unused TestUserMode parameter should be simplified:
remove the TestUserMode parameter from the constructor and remove the
`@Factory`(dataProvider = "configProvider") usage (and the corresponding
configProvider data provider method) so the test is no longer parameterized;
update or remove any imports related to TestUserMode and the data provider to
avoid unused imports and ensure the test runs as a single-configuration case.
- Around line 569-591: The methods createIdpInSubOrg and
createFederatedAssociationInSubOrg currently instantiate a fresh HttpClient
(HttpClients.createDefault()) and duplicate request setup; replace those fresh
clients with the already-configured test client created by createHttpClient()
(the class-level client field) and remove the duplicate client creation logic,
and refactor the shared header/entity setup (Authorization: Bearer
switchedM2MToken, Content-Type: application/json, User-Agent) into a small
helper used by both methods to prepare HttpPost requests; ensure you still close
responses but do not close the shared client.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0434cdd7-c97c-4f26-9dc9-cd4e46ece6ce

📥 Commits

Reviewing files that changed from the base of the PR and between 6d89ab9 and b0ace82.

📒 Files selected for processing (5)
  • modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserLegacyOrgAuthenticationTestCase.java
  • modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgAppFederatedAssociationTestCase.java
  • modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgApplicationAuthenticationTestCase.java
  • modules/integration/tests-integration/tests-backend/src/test/resources/org/wso2/identity/integration/test/oauth2/shared-user-federation-authorized-apis.json
  • modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml

Comment on lines +243 to +247
String userSearchReq = new JSONObject()
.put("schemas", new JSONArray().put("urn:ietf:params:scim:api:messages:2.0:SearchRequest"))
.put("attributes", new JSONArray().put("id"))
.put("filter", "userName eq " + ROOT_USER_USERNAME)
.toString();

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does a SCIM 2.0 SearchRequest filter require string literals to be quoted, e.g. userName eq "user"instead ofuserName eq user?

💡 Result:

Yes. In SCIM 2.0 SearchRequest filters, string comparison values are represented using JSON string syntax, which requires double quotes around the literal (e.g., userName eq "user"). This follows from the SCIM filter ABNF where compValue can be a JSON string, and the common examples show quoting (e.g., filter=userName eq "John"). [1][2][3] So, userName eq "user" is the correct form for a string literal, while userName eq user does not conform to the JSON-string-based grammar for string compValues and may be rejected or parsed unexpectedly by SCIM implementations. [2][3]

Citations:


Quote the SCIM filter value.

The SCIM 2.0 SearchRequest filter requires string literals to be quoted. The current code produces userName eq user, which does not conform to the SCIM filter specification and may be rejected by the SCIM endpoint. This could cause the readiness check to fail unexpectedly.

Suggested fix
-                .put("filter", "userName eq " + ROOT_USER_USERNAME)
+                .put("filter", "userName eq \"" + ROOT_USER_USERNAME + "\"")
🤖 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
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserLegacyOrgAuthenticationTestCase.java`
around lines 243 - 247, The SCIM filter string built in
SharedUserLegacyOrgAuthenticationTestCase (variable userSearchReq) is missing
quotes around the username; update the "filter" value to quote the string
literal (e.g., construct the filter as "userName eq \"<USERNAME>\"" using
ROOT_USER_USERNAME) so the SearchRequest conforms to SCIM 2.0 string literal
rules.

Comment on lines +350 to +354
String userSearchReq = new JSONObject()
.put("schemas", new JSONArray().put("urn:ietf:params:scim:api:messages:2.0:SearchRequest"))
.put("attributes", new JSONArray().put("id"))
.put("filter", "userName eq " + ROOT_USER_USERNAME)
.toString();

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how other tests in the same module construct SCIM "userName eq" filters.
rg -nP --type=java -C2 '"userName\s+eq\s'

Repository: wso2/product-is

Length of output: 10767


Add quotes around the SCIM filter value per RFC 7644 specification.

The filter value should be quoted as per RFC 7644 §3.4.2.2. String comparison values in SCIM filters must be wrapped in double quotes. The current code passes the value unquoted, which violates the specification and may behave inconsistently across SCIM implementations. Multiple other test files in the codebase correctly use the quoted format.

Proposed fix
-                .put("filter", "userName eq " + ROOT_USER_USERNAME)
+                .put("filter", "userName eq \"" + ROOT_USER_USERNAME + "\"")
🤖 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
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgAppFederatedAssociationTestCase.java`
around lines 350 - 354, The SCIM filter string in the userSearchReq JSON is
missing quotes around the comparison value; update the filter construction in
SharedUserSubOrgAppFederatedAssociationTestCase where userSearchReq is built so
the filter uses quoted string syntax per RFC 7644 (i.e., produce userName eq
"ROOT_USER_USERNAME" with proper escaping), ensuring the
JSONObject.put("filter", ...) uses the quoted form and still references the
ROOT_USER_USERNAME constant.

Comment on lines +227 to +234
String userSearchReq = new JSONObject()
.put("schemas", new JSONArray().put("urn:ietf:params:scim:api:messages:2.0:SearchRequest"))
.put("attributes", new JSONArray().put("id"))
.put("filter", "userName eq " + ROOT_USER_USERNAME)
.toString();

boolean isUserShared = scim2RestClient.isSharedUserCreationCompleted(userSearchReq, switchedM2MToken);
assertTrue(isUserShared, "User should be shared to the sub-organization.");

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find SCIM filter expressions in the test code to confirm quoting convention.
rg -nP --type=java -C2 '"\s*(userName|emails|name\.familyName)\s+eq\s+'

Repository: wso2/product-is

Length of output: 10767


Quote the string value in the SCIM 2.0 filter expression.

Per RFC 7644 (SCIM 2.0), string comparison values in filter expressions must be quoted. The current filter userName eq user is non-compliant with the specification. The codebase contains correct examples of quoted filters (see OutboundProvisioningTestUtils.buildEncodedUserNameFilter(), WorkflowSuccessTest, ClaimSelectiveStorageTestCase). Update to use userName eq "..." format.

Proposed fix
-                .put("filter", "userName eq " + ROOT_USER_USERNAME)
+                .put("filter", "userName eq \"" + ROOT_USER_USERNAME + "\"")
🤖 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
`@modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/identity/integration/test/oauth2/SharedUserSubOrgApplicationAuthenticationTestCase.java`
around lines 227 - 234, The SCIM filter string built for userSearchReq is
missing quotes around the username value; update the filter to use the
SCIM-compliant format userName eq "<value>" (e.g., wrap ROOT_USER_USERNAME in
quotes or use the existing helper like
OutboundProvisioningTestUtils.buildEncodedUserNameFilter()) before calling
scim2RestClient.isSharedUserCreationCompleted so the filter becomes quoted and
properly encoded for SCIM 2.0.

@jenkins-is-staging

Copy link
Copy Markdown
Contributor

PR builder completed
Link: https://github.com/wso2/product-is/actions/runs/25848494537
Status: failure

@Yasasr1

Yasasr1 commented May 25, 2026

Copy link
Copy Markdown
Contributor Author

#27587

@Yasasr1 Yasasr1 closed this May 25, 2026
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.

2 participants