Skip to content

[OB4] Fixes username resolving issue for secondary user store#912

Merged
Ashi1993 merged 1 commit intowso2:mainfrom
aka4rKO:main-username
Mar 11, 2026
Merged

[OB4] Fixes username resolving issue for secondary user store#912
Ashi1993 merged 1 commit intowso2:mainfrom
aka4rKO:main-username

Conversation

@aka4rKO
Copy link
Contributor

@aka4rKO aka4rKO commented Mar 10, 2026

[OB4] Fixes username resolving issue for secondary user store

Currently the username resolving logic checks if the username contains a UUID in the start of the username string which satisfies the regular userstore username: "95697b22-f380-45af-bb54-e12a9d74476b@carbon.super" however it fails to recognise the UUID in a case where a secondary user store is configured: "SECONDARY/8c10753e-30c0-4114-8675-42e0ac2aac63@carbon.super"

This PR fixes this issue by searching for a valid UUID pattern in the string and then passing that to the OAuth2Util.resolveUsernameFromUserId method which handles both these scenarios.

Issue link: **

Doc Issue: Optional, link issue from documentation repository

Applicable Labels: Spec, product, version, type (specify requested labels)


Development Checklist

  1. Built complete solution with pull request in place.
  2. Ran checkstyle plugin with pull request in place.
  3. Ran Findbugs plugin with pull request in place.
  4. Formatted code according to WSO2 code style.
  5. Migration scripts written (if applicable).

Secure Development Checklist

  1. Ran FindSecurityBugs plugin and verified report.
  2. Ran Dependency-check plugin and verified report for new dependencies added.
  3. Ran Dependency-check plugin and verified report for dependency version changes.
  4. Have you verify the PR does't commit any keys, passwords, tokens, usernames, or other secrets?
  5. Have you followed secure coding standards in WSO2 Secure Engineering Guidelines?

Testing Checklist

  1. Written unit tests.
  2. Documented test scenarios(link available in guides).
  3. Written automation tests (link available in guides).
  4. Verified tests in multiple database environments (if applicable).
  5. Verified tests in multiple deployed specifications (if applicable).
  6. Tested with OBBI enabled (if applicable).
  7. Tested with specification regulatory conformance suites (if applicable).

Automation Test Details

Test Suite Test Script IDs
Integration Suite TCXXXXX, TCXXXX

Conformance Tests Details

Test Suite Name Test Suite Version Scenarios Result
Security Suite VX.X Foo, Bar Passed

Summary by CodeRabbit

  • Refactor

    • Enhanced UUID detection to identify UUIDs anywhere within a string, not just at the beginning.
    • Added new UUID extraction capability for improved flexibility in UUID handling.
  • Tests

    • Expanded test coverage for UUID utility functions, including additional edge cases and various string formats.

Comment on lines 146 to +148
public static String resolveUsernameFromUserId(String userID) {

if (!startsWithUUID(userID)) {
// If the user ID is not starting with a UUID that means request has sent the username,
if (!containsUUID(userID)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Log Improvement Suggestion No: 1

Suggested change
public static String resolveUsernameFromUserId(String userID) {
if (!startsWithUUID(userID)) {
// If the user ID is not starting with a UUID that means request has sent the username,
if (!containsUUID(userID)) {
public static String resolveUsernameFromUserId(String userID) {
log.debug("Attempting to resolve username from user ID");
if (!containsUUID(userID)) {

Comment on lines +154 to 155
String extractedUUID = extractUUID(userID);
try {
Copy link
Contributor

Choose a reason for hiding this comment

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

Log Improvement Suggestion No: 2

Suggested change
String extractedUUID = extractUUID(userID);
try {
String extractedUUID = extractUUID(userID);
if (log.isDebugEnabled()) {
log.debug("Extracted UUID from user ID: " + (extractedUUID != null ? "UUID found" : "UUID not found"));
}
try {

Copy link
Contributor

@wso2-engineering wso2-engineering bot left a comment

Choose a reason for hiding this comment

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

AI Agent Log Improvement Checklist

⚠️ Warning: AI-Generated Review Comments

  • The log-related comments and suggestions in this review were generated by an AI tool to assist with identifying potential improvements. Purpose of reviewing the code for log improvements is to improve the troubleshooting capabilities of our products.
  • Please make sure to manually review and validate all suggestions before applying any changes. Not every code suggestion would make sense or add value to our purpose. Therefore, you have the freedom to decide which of the suggestions are helpful.

✅ Before merging this pull request:

  • Review all AI-generated comments for accuracy and relevance.
  • Complete and verify the table below. We need your feedback to measure the accuracy of these suggestions and the value they add. If you are rejecting a certain code suggestion, please mention the reason briefly in the suggestion for us to capture it.
Comment Accepted (Y/N) Reason
#### Log Improvement Suggestion No: 1
#### Log Improvement Suggestion No: 2

@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

Walkthrough

UUID utility methods in a financial services accelerator are refactored to check for UUID presence anywhere in strings instead of only at the start, and a new extraction utility is introduced. The test suite is updated to reflect the method renames and includes comprehensive test coverage for the new extraction functionality.

Changes

Cohort / File(s) Summary
UUID Utility Refactoring
FinancialServicesUtils.java, FinancialServicesUtilsTest.java
Replaced startsWithUUID() method with containsUUID() for flexible UUID detection anywhere in strings. Added new extractUUID() method to extract UUID substrings using regex. Updated corresponding test suite with renamed test method and new comprehensive test cases for UUID extraction logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Hopping through UUID strings, we now seek,
Not just at the start, but everywhere we peek!
Extract and contain, with regex so bright,
Utilities refactored, the logic feels right!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description includes the required template structure with clear problem explanation, technical approach, and multiple checklists. However, the Issue link field is empty (critical required field), and several security/testing items remain incomplete. Add the GitHub issue link in the 'Issue link:' field (currently shows '**'), which is marked as required in the template. Complete remaining security and testing checklist items or mark as not applicable.
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main fix: addressing a username resolving issue for secondary user stores, which matches the primary objective of the changeset.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
financial-services-accelerator/components/org.wso2.financial.services.accelerator.common/src/test/java/org/wso2/financial/services/accelerator/common/test/util/FinancialServicesUtilsTest.java (1)

77-103: Add a regression test for resolveUsernameFromUserId(...) itself.

These tests validate the regex helpers, but the bug fixed in this PR is in the wrapper that extracts the UUID and delegates to OAuth2Util. A direct test for SECONDARY/<uuid>@carbon.super would protect the actual regression path.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@financial-services-accelerator/components/org.wso2.financial.services.accelerator.common/src/test/java/org/wso2/financial/services/accelerator/common/test/util/FinancialServicesUtilsTest.java`
around lines 77 - 103, Add a unit test in FinancialServicesUtilsTest that
verifies resolveUsernameFromUserId correctly handles the
"SECONDARY/<uuid>@carbon.super" form and delegates to OAuth2Util: generate a
UUID, stub/mock OAuth2Util.getUserFromUserId(...) to return a known username,
call
FinancialServicesUtils.resolveUsernameFromUserId("SECONDARY/"+uuid+"@carbon.super"),
and assert the returned value equals the stubbed username; this directly tests
the wrapper method resolveUsernameFromUserId and prevents regressions in the
UUID-extraction + delegation path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@financial-services-accelerator/components/org.wso2.financial.services.accelerator.common/src/main/java/org/wso2/financial/services/accelerator/common/util/FinancialServicesUtils.java`:
- Around line 193-195: containsUUID throws NPE when input is null because
Pattern.matcher(...) doesn't accept null; update the containsUUID(String input)
method to first check for null (and optionally empty/blank) and return false
immediately, then proceed to compile/use FinancialServicesConstants.UUID_REGEX
and matcher; ensure callers like resolveUsernameFromUserId(...) will get false
for missing user IDs instead of an exception.
- Around line 155-159: The helper in FinancialServicesUtils currently swallows
UserStoreException and returns null; change it so it never returns null on
lookup failure—either rethrow the UserStoreException (or wrap it in a runtime
exception like IdentityRuntimeException) from the method so callers see an
explicit failure, or return a non-null sentinel (e.g. empty string or a
constant) instead of null so callers like DefaultConsentValidator (which calls
.equals()) won't NPE; update the catch block around
OAuth2Util.resolveUsernameFromUserId to implement one of these two behaviours
and adjust any callers if you choose to surface the exception.

---

Nitpick comments:
In
`@financial-services-accelerator/components/org.wso2.financial.services.accelerator.common/src/test/java/org/wso2/financial/services/accelerator/common/test/util/FinancialServicesUtilsTest.java`:
- Around line 77-103: Add a unit test in FinancialServicesUtilsTest that
verifies resolveUsernameFromUserId correctly handles the
"SECONDARY/<uuid>@carbon.super" form and delegates to OAuth2Util: generate a
UUID, stub/mock OAuth2Util.getUserFromUserId(...) to return a known username,
call
FinancialServicesUtils.resolveUsernameFromUserId("SECONDARY/"+uuid+"@carbon.super"),
and assert the returned value equals the stubbed username; this directly tests
the wrapper method resolveUsernameFromUserId and prevents regressions in the
UUID-extraction + delegation path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 625c7119-25a8-4b0d-8483-bfd6cb520d20

📥 Commits

Reviewing files that changed from the base of the PR and between 52288bc and 1f3cfd2.

📒 Files selected for processing (2)
  • financial-services-accelerator/components/org.wso2.financial.services.accelerator.common/src/main/java/org/wso2/financial/services/accelerator/common/util/FinancialServicesUtils.java
  • financial-services-accelerator/components/org.wso2.financial.services.accelerator.common/src/test/java/org/wso2/financial/services/accelerator/common/test/util/FinancialServicesUtilsTest.java

Comment on lines 155 to 159
try {
if (userID.contains(FinancialServicesConstants.TENANT_DOMAIN)) {
username = OAuth2Util.resolveUsernameFromUserId(FinancialServicesConstants.TENANT_DOMAIN,
userID.split("@" + FinancialServicesConstants.TENANT_DOMAIN)[0]);
} else {
username = OAuth2Util.resolveUsernameFromUserId(FinancialServicesConstants.TENANT_DOMAIN, userID);
}
return OAuth2Util.resolveUsernameFromUserId(FinancialServicesConstants.TENANT_DOMAIN, extractedUUID);
} catch (UserStoreException e) {
log.debug("Returning null since user ID is not found in the database", e);
return null;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don't turn lookup failures into null.

DefaultConsentValidator.java, Lines 95-101 immediately call .equals() on the return value from this helper. Returning null here converts an unresolved secondary-store user into an NPE/500 instead of a normal validation failure. Please keep this method non-null on lookup miss, or surface the failure explicitly.

Possible fix
         try {
             return OAuth2Util.resolveUsernameFromUserId(FinancialServicesConstants.TENANT_DOMAIN, extractedUUID);
         } catch (UserStoreException e) {
-            log.debug("Returning null since user ID is not found in the database", e);
-            return null;
+            log.debug("Unable to resolve username from user ID. Falling back to original identifier.", e);
+            return userID;
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
if (userID.contains(FinancialServicesConstants.TENANT_DOMAIN)) {
username = OAuth2Util.resolveUsernameFromUserId(FinancialServicesConstants.TENANT_DOMAIN,
userID.split("@" + FinancialServicesConstants.TENANT_DOMAIN)[0]);
} else {
username = OAuth2Util.resolveUsernameFromUserId(FinancialServicesConstants.TENANT_DOMAIN, userID);
}
return OAuth2Util.resolveUsernameFromUserId(FinancialServicesConstants.TENANT_DOMAIN, extractedUUID);
} catch (UserStoreException e) {
log.debug("Returning null since user ID is not found in the database", e);
return null;
try {
return OAuth2Util.resolveUsernameFromUserId(FinancialServicesConstants.TENANT_DOMAIN, extractedUUID);
} catch (UserStoreException e) {
log.debug("Unable to resolve username from user ID. Falling back to original identifier.", e);
return userID;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@financial-services-accelerator/components/org.wso2.financial.services.accelerator.common/src/main/java/org/wso2/financial/services/accelerator/common/util/FinancialServicesUtils.java`
around lines 155 - 159, The helper in FinancialServicesUtils currently swallows
UserStoreException and returns null; change it so it never returns null on
lookup failure—either rethrow the UserStoreException (or wrap it in a runtime
exception like IdentityRuntimeException) from the method so callers see an
explicit failure, or return a non-null sentinel (e.g. empty string or a
constant) instead of null so callers like DefaultConsentValidator (which calls
.equals()) won't NPE; update the catch block around
OAuth2Util.resolveUsernameFromUserId to implement one of these two behaviours
and adjust any callers if you choose to surface the exception.

Comment on lines +193 to +195
public static boolean containsUUID(String input) {
Pattern uuidPattern = Pattern.compile(FinancialServicesConstants.UUID_REGEX);
return uuidPattern.matcher(input).find();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Handle null in containsUUID.

extractUUID(null) already treats null as “no UUID”, but this method throws because Pattern.matcher(...) does not accept null. Since resolveUsernameFromUserId(...) now calls this first, a missing user ID becomes an unexpected NPE.

Possible fix
     public static boolean containsUUID(String input) {
+        if (input == null) {
+            return false;
+        }
         Pattern uuidPattern = Pattern.compile(FinancialServicesConstants.UUID_REGEX);
         return uuidPattern.matcher(input).find();
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@financial-services-accelerator/components/org.wso2.financial.services.accelerator.common/src/main/java/org/wso2/financial/services/accelerator/common/util/FinancialServicesUtils.java`
around lines 193 - 195, containsUUID throws NPE when input is null because
Pattern.matcher(...) doesn't accept null; update the containsUUID(String input)
method to first check for null (and optionally empty/blank) and return false
immediately, then proceed to compile/use FinancialServicesConstants.UUID_REGEX
and matcher; ensure callers like resolveUsernameFromUserId(...) will get false
for missing user IDs instead of an exception.

@Ashi1993 Ashi1993 merged commit d08c5ec into wso2:main Mar 11, 2026
2 checks passed
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.

3 participants