Skip to content

Retain tenant qualification for configured server URL in account recovery endpoint#8196

Open
ThaminduR wants to merge 1 commit into
wso2:masterfrom
ThaminduR:fix-configured-server-url-tenant-qualification
Open

Retain tenant qualification for configured server URL in account recovery endpoint#8196
ThaminduR wants to merge 1 commit into
wso2:masterfrom
ThaminduR:fix-configured-server-url-tenant-qualification

Conversation

@ThaminduR

Copy link
Copy Markdown
Contributor

Purpose

IdentityManagementEndpointUtil.getBasePath() drops the /t/<tenant> segment from the account recovery endpoint's internal REST calls when a server URL is configured (identity_server_service_url) and tenant-qualified URLs are enabled.

The configured-server-URL branch reused isServerURLAlreadyTenanted(), which inspects the inbound request path rather than the configured URL. For a non-super tenant the inbound path is already tenant-qualified, so the guard dropped the tenant prefix and the internal call resolved against carbon.super. This caused tenant self-registration confirmation (and related recovery flows) to fail with Invalid tenant 'carbon.super'.

Approach

In the configured-server-URL branch, decide tenant qualification from the configured URL itself (serverUrl.contains("/t/")) instead of the inbound request path, and append /t/<tenant> when it is not already present. The blank-server-URL branch is unchanged. Keying off the configured URL also avoids a double /t/<tenant>/t/<tenant> prefix when a tenant is baked into the configured URL.

Added regression coverage in IdentityManagementEndpointUtilTest for the configured-server-URL branch with a tenant-qualified inbound path (previously uncovered), plus the already-tenanted-URL, super-tenant, and non-tenant-aware cases.

Testing

IdentityManagementEndpointUtilTest passes (JDK 21, module build), including the new cases.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The tenant qualification check in IdentityManagementEndpointUtil's getBasePath method was changed to test for the presence of a tenant context prefix in the configured server URL rather than relying on the prior tenant-check logic. A corresponding data-driven test case was added to validate this behavior.

Changes

Tenant Qualification Fix

Layer / File(s) Summary
Configured server URL tenant check and validation
.../IdentityManagementEndpointUtil.java, .../IdentityManagementEndpointUtilTest.java
The guard for appending a tenant-qualified context to a configured server URL now checks for FrameworkConstants.TENANT_CONTEXT_PREFIX in serverUrl instead of using isServerURLAlreadyTenanted(tenantDomain), with clarifying comments; a new @DataProvider and test method validate base path results across inbound-path, super tenant, and non-endpoint-tenant-aware scenarios.

Estimated code review effort

3/5 (Medium) — logic change affects tenant-context resolution and is covered by new tests, but the diff is small and localized.

Suggested labels: bug, tests

Suggested reviewers: (based on repository conventions, assign identity-mgt component maintainers)


🤖 A tiny prefix, once misjudged,
Now checks the URL truly nudged,
Tenants qualified, paths aligned right,
Tests confirm the fix takes flight,
No more segments lost from sight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers purpose, approach, and testing, but omits many required template sections like Goals, Release note, Documentation, and Security checks. Add the missing template sections or mark non-applicable items as N/A, especially Goals, Release note, Documentation, Security checks, Test environment, and Related PRs.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the core fix: preserving tenant qualification for configured server URLs in account recovery.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

@jenkins-is-staging

Copy link
Copy Markdown

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

@sonarqubecloud

sonarqubecloud Bot commented Jul 7, 2026

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.

🧹 Nitpick comments (2)
components/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/src/main/java/org/wso2/carbon/identity/mgt/endpoint/util/IdentityManagementEndpointUtil.java (1)

901-909: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider a debug log at this tenant-qualification decision point.

This branch was the root cause of the Invalid tenant 'carbon.super' regression described in the PR. A guarded DEBUG log recording the computed basePath (and whether the tenant prefix was appended) would aid future diagnosis of similar tenant-resolution issues without touching hot-path cost, since it is guarded by isDebugEnabled().

💡 Optional debug log
             } else {
                 // A configured server URL is a bare base URL, so qualify it with the tenant here unless it
                 // already carries one.
                 if (StringUtils.isNotBlank(tenantDomain) && !MultitenantConstants.SUPER_TENANT_DOMAIN_NAME
                         .equalsIgnoreCase(tenantDomain) && isEndpointTenantAware
                         && !serverUrl.contains(FrameworkConstants.TENANT_CONTEXT_PREFIX)) {
                     basePath = serverUrl + FrameworkConstants.TENANT_CONTEXT_PREFIX + tenantDomain + context;
                 } else {
                     basePath = serverUrl + context;
                 }
+                if (log.isDebugEnabled()) {
+                    log.debug("Resolved base path for configured server URL: " + basePath);
+                }
             }

As per path instructions, "Flag entry/exit points of critical services that don't log their invocation and suggest appropriate logs for those points if possible."

🤖 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/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/src/main/java/org/wso2/carbon/identity/mgt/endpoint/util/IdentityManagementEndpointUtil.java`
around lines 901 - 909, Add a guarded DEBUG log at the tenant-qualification
branch in IdentityManagementEndpointUtil where basePath is computed, so this
decision point can be traced when tenant resolution goes wrong. Use the existing
tenant-aware URL logic around the serverUrl/context assignment to log the
computed basePath and whether the tenant prefix was appended, and keep it behind
isDebugEnabled() so there is no hot-path overhead.

Source: Path instructions

components/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/src/test/java/org/wso2/carbon/identity/mgt/endpoint/util/IdentityManagementEndpointUtilTest.java (1)

376-430: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

inboundPath stub is inert for this branch; comment is misleading.

Since contextUrl is always non-blank in this data set, getBasePath takes the configured-serverUrl branch, which no longer consults serviceURL.getPath() at all — that's exactly the fix. Stubbing serviceURL.getPath() with inboundPath and labelling it "the case that regressed" doesn't actually exercise anything; the assertions pass purely based on serverUrl content. Worth simplifying the data provider (drop the unused inboundPath parameter/stub) or rewording the comment so it doesn't suggest the inbound path still matters for this branch.

♻️ Simplify by dropping the unused inboundPath stub
-    `@DataProvider`(name = "getBasePathConfiguredServerUrlData")
-    public Object[][] getBasePathConfiguredServerUrlData() {
-
-        return new Object[][] {
-                // contextUrl (configured server URL)
-                // tenantDomain
-                // isEndpointTenantAware
-                // inboundPath (stubbed serviceURL.getPath() - already tenant-qualified, the case that regressed)
-                // expected value
-
-                // A configured server URL is tenant-qualified even when the inbound request path already
-                // carries the tenant (the fix - the tenant must not be dropped here).
-                { "https://foo.com",
-                  SAMPLE_TENANT_DOMAIN,
-                  true,
-                  "/t/test.com/api/identity/recovery/v0.9",
-                  "https://foo.com/t/test.com/api/identity/recovery/v0.9"
-                },
+    `@DataProvider`(name = "getBasePathConfiguredServerUrlData")
+    public Object[][] getBasePathConfiguredServerUrlData() {
+
+        return new Object[][] {
+                // contextUrl (configured server URL), tenantDomain, isEndpointTenantAware, expected value.
+
+                // Bare configured server URL is qualified with the tenant.
+                { "https://foo.com",
+                  SAMPLE_TENANT_DOMAIN,
+                  true,
+                  "https://foo.com/t/test.com/api/identity/recovery/v0.9"
+                },
             ...
-    `@Test`(dataProvider = "getBasePathConfiguredServerUrlData")
-    public void testGetBasePathConfiguredServerUrl(String contextUrl, String tenantDomain,
-            boolean isEndpointTenantAware, String inboundPath, String expected) throws Exception {
-
-        String context = IdentityManagementEndpointConstants.UserInfoRecovery.RECOVERY_API_RELATIVE_PATH;
-        try (MockedStatic<IdentityTenantUtil> identityTenantUtil = mockStatic(IdentityTenantUtil.class);
-             MockedStatic<ServiceURLBuilder> serviceURLBuilder = mockStatic(ServiceURLBuilder.class)) {
-            prepareGetBasePathTest(contextUrl, context, identityTenantUtil, serviceURLBuilder, true, false);
-            lenient().when(serviceURL.getPath()).thenReturn(inboundPath);
-            assertEquals(IdentityManagementEndpointUtil.getBasePath(tenantDomain, context, isEndpointTenantAware),
-                    expected);
-        }
-    }
+    `@Test`(dataProvider = "getBasePathConfiguredServerUrlData")
+    public void testGetBasePathConfiguredServerUrl(String contextUrl, String tenantDomain,
+            boolean isEndpointTenantAware, String expected) throws Exception {
+
+        String context = IdentityManagementEndpointConstants.UserInfoRecovery.RECOVERY_API_RELATIVE_PATH;
+        try (MockedStatic<IdentityTenantUtil> identityTenantUtil = mockStatic(IdentityTenantUtil.class);
+             MockedStatic<ServiceURLBuilder> serviceURLBuilder = mockStatic(ServiceURLBuilder.class)) {
+            prepareGetBasePathTest(contextUrl, context, identityTenantUtil, serviceURLBuilder, true, false);
+            assertEquals(IdentityManagementEndpointUtil.getBasePath(tenantDomain, context, isEndpointTenantAware),
+                    expected);
+        }
+    }
🤖 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/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/src/test/java/org/wso2/carbon/identity/mgt/endpoint/util/IdentityManagementEndpointUtilTest.java`
around lines 376 - 430, The test data in
IdentityManagementEndpointUtilTest.testGetBasePathConfiguredServerUrl is
misleading because getBasePath now always takes the configured-serverUrl branch
when contextUrl is set, so the inboundPath stub on serviceURL.getPath() is
unused. Simplify the test by removing the inboundPath parameter and lenient
serviceURL.getPath() stubbing from
getBasePathConfiguredServerUrlData/testGetBasePathConfiguredServerUrl, or reword
the comments to clearly state that only contextUrl/serverUrl and tenant
awareness determine the result in this branch.
🤖 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.

Nitpick comments:
In
`@components/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/src/main/java/org/wso2/carbon/identity/mgt/endpoint/util/IdentityManagementEndpointUtil.java`:
- Around line 901-909: Add a guarded DEBUG log at the tenant-qualification
branch in IdentityManagementEndpointUtil where basePath is computed, so this
decision point can be traced when tenant resolution goes wrong. Use the existing
tenant-aware URL logic around the serverUrl/context assignment to log the
computed basePath and whether the tenant prefix was appended, and keep it behind
isDebugEnabled() so there is no hot-path overhead.

In
`@components/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/src/test/java/org/wso2/carbon/identity/mgt/endpoint/util/IdentityManagementEndpointUtilTest.java`:
- Around line 376-430: The test data in
IdentityManagementEndpointUtilTest.testGetBasePathConfiguredServerUrl is
misleading because getBasePath now always takes the configured-serverUrl branch
when contextUrl is set, so the inboundPath stub on serviceURL.getPath() is
unused. Simplify the test by removing the inboundPath parameter and lenient
serviceURL.getPath() stubbing from
getBasePathConfiguredServerUrlData/testGetBasePathConfiguredServerUrl, or reword
the comments to clearly state that only contextUrl/serverUrl and tenant
awareness determine the result in this branch.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 03ec5716-1853-41b2-8223-b06a331ec2b4

📥 Commits

Reviewing files that changed from the base of the PR and between 64d0af8 and b0be03a.

📒 Files selected for processing (2)
  • components/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/src/main/java/org/wso2/carbon/identity/mgt/endpoint/util/IdentityManagementEndpointUtil.java
  • components/identity-mgt/org.wso2.carbon.identity.mgt.endpoint.util/src/test/java/org/wso2/carbon/identity/mgt/endpoint/util/IdentityManagementEndpointUtilTest.java

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.98%. Comparing base (64d0af8) to head (b0be03a).

Additional details and impacted files
@@            Coverage Diff            @@
##             master    #8196   +/-   ##
=========================================
  Coverage     52.98%   52.98%           
+ Complexity    21087    21041   -46     
=========================================
  Files          2197     2197           
  Lines        129494   129494           
  Branches      19370    19370           
=========================================
+ Hits          68612    68613    +1     
  Misses        52506    52506           
+ Partials       8376     8375    -1     
Flag Coverage Δ
unit 38.26% <100.00%> (-0.01%) ⬇️

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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jenkins-is-staging

Copy link
Copy Markdown

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

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