-
Notifications
You must be signed in to change notification settings - Fork 169
Introduce end user credential management admin API #1008
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
...n/identity/api/server/credential/management/common/impl/CredentialManagementServiceImpl.java
Outdated
Show resolved
Hide resolved
...n/identity/api/server/credential/management/common/impl/CredentialManagementServiceImpl.java
Outdated
Show resolved
Hide resolved
...n/identity/api/server/credential/management/common/impl/CredentialManagementServiceImpl.java
Outdated
Show resolved
Hide resolved
...2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java
Show resolved
Hide resolved
...2/carbon/identity/api/server/credential/management/common/impl/PasskeyCredentialHandler.java
Outdated
Show resolved
Hide resolved
...2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java
Show resolved
Hide resolved
...2/carbon/identity/api/server/credential/management/common/impl/PasskeyCredentialHandler.java
Outdated
Show resolved
Hide resolved
...2/carbon/identity/api/server/credential/management/common/impl/PasskeyCredentialHandler.java
Outdated
Show resolved
Hide resolved
...2/carbon/identity/api/server/credential/management/common/impl/PasskeyCredentialHandler.java
Show resolved
Hide resolved
...wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java
Show resolved
Hide resolved
...wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java
Show resolved
Hide resolved
...wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java
Show resolved
Hide resolved
...wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java
Show resolved
Hide resolved
...wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java
Show resolved
Hide resolved
...carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java
Show resolved
Hide resolved
...y/api/server/user/credential/management/v1/core/UserCredentialManagementServiceImplTest.java
Outdated
Show resolved
Hide resolved
...bon/identity/api/server/credential/management/v1/core/ServerCredentialManagementService.java
Outdated
Show resolved
Hide resolved
| CredentialMgtEndpointUtils.validateUserId(userId); | ||
| CredentialMgtEndpointUtils.validateCredentialId(credentialId); | ||
| CredentialMgtEndpointUtils.validateCredentialType(type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log Improvement Suggestion No: 18
| CredentialMgtEndpointUtils.validateUserId(userId); | |
| CredentialMgtEndpointUtils.validateCredentialId(credentialId); | |
| CredentialMgtEndpointUtils.validateCredentialType(type); | |
| CredentialMgtEndpointUtils.validateCredentialId(credentialId); | |
| CredentialMgtEndpointUtils.validateCredentialType(type); | |
| log.info("Deleting credential of type: {} for user: {}", type, userId); | |
| adminCredentialManagementService.deleteCredentialForUser(userId, type, credentialId); |
.../wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialApiServiceImpl.java
Outdated
Show resolved
Hide resolved
.../wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialApiServiceImpl.java
Show resolved
Hide resolved
.../wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialApiServiceImpl.java
Outdated
Show resolved
Hide resolved
...o2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java
Show resolved
Hide resolved
...o2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java
Show resolved
Hide resolved
...o2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java
Show resolved
Hide resolved
...o2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java
Outdated
Show resolved
Hide resolved
...o2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java
Outdated
Show resolved
Hide resolved
...o2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java
Show resolved
Hide resolved
...o2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java
Show resolved
Hide resolved
...o2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java
Show resolved
Hide resolved
...o2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java
Show resolved
Hide resolved
| */ | ||
| public static void validateCredentialType(String value) throws CredentialMgtClientException { | ||
|
|
||
| if (StringUtils.isBlank(value) || !CredentialTypes.fromString(value).isPresent()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (StringUtils.isBlank(value) || !CredentialTypes.fromString(value).isPresent()) { | |
| if (!CredentialTypes.fromString(value).isPresent()) { |
| * @param userId User ID. | ||
| * @throws CredentialMgtClientException Invalid user ID. | ||
| */ | ||
| public static void validateUserId(String userId) throws CredentialMgtClientException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this util
| try { | ||
| this.adminServerCredentialManagementService = ServerCredentialManagementServiceFactory | ||
| .getServerCredentialManagementService(); | ||
| } catch (IllegalStateException e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this
| } | ||
|
|
||
| @Override | ||
| public void deleteCredentialForUser(String userId, String credentialId) throws CredentialMgtException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Introduce a data model and extract as necessary
3efd6bb to
57f64af
Compare
45c212f to
c077ff8
Compare
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughAdds a new credential-management multi-module (common + v1) implementing credential retrieval and deletion for passkey (FIDO2) and push-auth devices: service interfaces, handlers, DTOs, exceptions, endpoint utils, OpenAPI spec, factory, REST impl, Maven configs, and unit tests. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant API as UsersCredentialApiServiceImpl
participant Service as CredentialManagementServiceImpl
participant Factory as CredentialManagementServiceFactory
participant PK as PasskeyCredentialHandler
participant Push as PushCredentialHandler
participant WebAuthn as WebAuthnService
participant Device as DeviceHandlerService
participant Utils as CredentialMgtEndpointUtils
rect rgb(220,235,255)
Note over Client,Utils: GET /users/{userId}/credentials
Client->>API: GET /users/{userId}/credentials
API->>Service: getCredentials(userId)
Service->>PK: getCredentials(userId)
PK->>WebAuthn: fetch registrations
WebAuthn-->>PK: registrations
PK-->>Service: CredentialDTOs
Service->>Push: getCredentials(userId)
Push->>Device: fetch devices
Device-->>Push: devices
Push-->>Service: CredentialDTOs
Service-->>API: aggregated CredentialDTOs
API->>Utils: toCredentialResponse(...)
Utils-->>API: API models
API-->>Client: 200 OK + payload
end
rect rgb(255,235,220)
Note over Client,Utils: DELETE /users/{userId}/credentials/{type}/{credentialId}
Client->>API: DELETE /users/{userId}/credentials/{type}/{id}
API->>Service: deleteCredential(request)
Service->>Service: normalize type → CredentialTypes
alt PASSKEY
Service->>PK: deleteCredential(request)
PK->>WebAuthn: deregister credential
WebAuthn-->>PK: success/error
else PUSH_AUTH
Service->>Push: deleteCredential(request)
Push->>Device: unregister device
Device-->>Push: success/error
end
Service-->>API: success / throws CredentialMgtException
API->>Utils: handleCredentialMgtException(e) (if thrown)
Utils-->>API: APIError / mapped response
API-->>Client: 204 No Content or error
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Areas requiring extra attention:
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 14
♻️ Duplicate comments (2)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
99-102: Remove double spaces in error descriptions.Lines 100 and 102 contain double spaces before "was" in the error descriptions. Clean up these formatting inconsistencies.
Apply this diff:
ERROR_CODE_DELETE_PASSKEY_CREDENTIAL("60001", "Error deleting credential.", - "The request to delete the passkey credential: %s was invalid."), + "The request to delete the passkey credential: %s was invalid."), ERROR_CODE_DELETE_PUSH_AUTH_CREDENTIAL("60002", "Error deleting credential.", - "The request to delete the push auth credential: %s was invalid."), + "The request to delete the push auth credential: %s was invalid."),components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (1)
75-77: HTTP spec violation: 204 NO_CONTENT cannot have a response body.While preventing user ID enumeration is a valid security pattern, returning
Response.Status.NO_CONTENT(204) with an error body violates HTTP semantics. RFC 7231 specifies that 204 responses MUST NOT contain a message body, yet line 94 constructs anAPIErrorwith anErrorDTObody that will be serialized.Consider these alternatives:
- Return 200 OK with an empty credentials array (semantically correct for "no credentials found")
- Return 404 NOT_FOUND with a generic message that doesn't reveal whether the user or credential is missing
- Return 400 BAD_REQUEST with a generic validation error
Apply this diff to return an empty result instead:
- if (StringUtils.equals(e.getErrorCode(), - CredentialManagementConstants.ErrorMessages.ERROR_CODE_ENTITY_NOT_FOUND.getCode())) { - status = Response.Status.NO_CONTENT; - } else { + if (!StringUtils.equals(e.getErrorCode(), + CredentialManagementConstants.ErrorMessages.ERROR_CODE_ENTITY_NOT_FOUND.getCode())) { status = Response.Status.BAD_REQUEST; }Note: This approach treats entity-not-found as a success case (avoiding enumeration), while other client errors return 400. The caller must handle the distinction between empty results and errors.
🧹 Nitpick comments (9)
components/org.wso2.carbon.identity.api.server.user.credential.management/org.wso2.carbon.identity.api.server.user.credential.management.v1/src/test/resources/testng.xml (1)
21-26: Consider aligning suite name with test class package.The suite is named
org.wso2.carbon.identity.api.server.credential.management.common, but the test class is in packageorg.wso2.carbon.identity.api.server.user.credential.management.v1.core. While this may be intentional organizational grouping, aligning the suite name with the actual test package would improve clarity and consistency.components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/pom.xml (1)
123-161: Consider automating the API service implementation renaming step.The commented OpenAPI generator configuration notes that the service implementation class requires manual renaming to
*UsersCredentialApiServiceImpl.javaafter generation. Manual post-generation steps are error-prone and can be easily forgotten during updates.Consider configuring the OpenAPI generator to produce the correct naming directly (e.g., using custom templates or generator configuration options), or document this manual step prominently in a README or CONTRIBUTING guide.
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (1)
35-41: Consider singleton pattern for factory.The factory creates new
PasskeyCredentialHandlerandPushCredentialHandlerinstances on every invocation. If this factory is called multiple times per request or across requests, unnecessary object allocation occurs.If the handlers are stateless (as they appear to be), consider implementing a singleton pattern:
+private static final CredentialManagementServiceImpl INSTANCE; + +static { + Map<CredentialTypes, CredentialHandler> handlerMap = new EnumMap<>(CredentialTypes.class); + handlerMap.put(CredentialTypes.PASSKEY, new PasskeyCredentialHandler()); + handlerMap.put(CredentialTypes.PUSH_AUTH, new PushCredentialHandler()); + INSTANCE = new CredentialManagementServiceImpl(handlerMap); +} + public static CredentialManagementServiceImpl getCredentialManagementService() { - Map<CredentialTypes, CredentialHandler> handlerMap = new EnumMap<>(CredentialTypes.class); - handlerMap.put(CredentialTypes.PASSKEY, new PasskeyCredentialHandler()); - handlerMap.put(CredentialTypes.PUSH_AUTH, new PushCredentialHandler()); - return new CredentialManagementServiceImpl(handlerMap); + return INSTANCE; }components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml (1)
44-52: Consider adding maxItems constraint on credential arrays.The response schema returns an unbounded array of credentials. For production APIs, consider adding a
maxItemsconstraint to prevent potential performance issues when users have many credentials enrolled.Apply this diff:
'200': description: OK content: application/json: schema: type: array + maxItems: 100 items: $ref: '#/components/schemas/Credential'components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (1)
56-63: Exception from one handler stops retrieval from other handlers.If the first handler throws an exception, credentials from subsequent handlers won't be retrieved. Consider whether partial results should be returned or if this fail-fast behavior is intentional.
If partial results are acceptable, consider collecting errors and continuing with other handlers:
List<CredentialDTO> allCredentials = new ArrayList<>(); List<CredentialMgtException> errors = new ArrayList<>(); for (CredentialHandler handler : handlerMap.values()) { try { allCredentials.addAll(handler.getCredentials(entityId)); } catch (CredentialMgtException e) { errors.add(e); LOG.warn("Failed to retrieve credentials from handler: " + handler.getClass().getName(), e); } } // Handle errors if neededcomponents/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (1)
43-51: Consider handlingIllegalFormatExceptionfromString.format.If the
dataarguments don't match the format specifiers inerror.getDescription(),String.formatwill throw anIllegalFormatException. Consider wrapping in a try-catch or validating the format.public static CredentialMgtServerException handleServerException(ErrorMessages error, Throwable e, Object... data) { String description = error.getDescription(); if (ArrayUtils.isNotEmpty(data)) { - description = String.format(description, data); + try { + description = String.format(description, data); + } catch (IllegalFormatException ex) { + // Log the formatting error and use the original description + description = error.getDescription() + " [Data: " + Arrays.toString(data) + "]"; + } } return new CredentialMgtServerException(error.getCode(), error.getMessage(), description, e); }components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
78-96: Consider makingerrorCodeanddescriptionfields immutable.The protected setters allow mutation after construction. If immutability is preferred for exception classes, consider removing the setters or making the fields final.
If the setters aren't used by subclasses, consider:
- private String errorCode; - private String description; + private final String errorCode; + private final String description;And remove the setter methods. This ensures exception state cannot change after construction.
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (2)
120-126: Consider explicit blank check for clarity.While
CredentialTypes.fromStringhandles blank/null values, explicitly checking for blank strings before the enum lookup would improve readability and avoid unnecessary processing.Apply this diff:
public static void validateCredentialType(String value) throws CredentialMgtClientException { - if (!CredentialTypes.fromString(value).isPresent()) { + if (StringUtils.isBlank(value) || !CredentialTypes.fromString(value).isPresent()) { throw new CredentialMgtClientException(CredentialManagementConstants .ErrorMessages.ERROR_CODE_INVALID_CREDENTIAL_TYPE); }
171-180: Document unchecked exception behavior.The method throws
APIError(unchecked) when encountering an invalid credential type. While functionally correct, documenting this behavior would improve maintainability, especially since it's called from a stream operation.Consider adding a JavaDoc comment:
/** * Convert a CredentialDTO to a Credential response object. * * @param dto CredentialDTO object. * @return Credential response object. + * @throws APIError if the credential type cannot be mapped (unchecked). */ private static Credential toCredential(CredentialDTO dto) {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/Credential.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/Error.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/UsersApi.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/UsersApiService.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/UsersApiServiceFactory.javais excluded by!**/gen/**
📒 Files selected for processing (23)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/pom.xml(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialHandler.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementService.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/pom.xml(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/constants/CredentialMgtEndpointConstants.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/pom.xml(1 hunks)components/org.wso2.carbon.identity.api.server.user.credential.management/org.wso2.carbon.identity.api.server.user.credential.management.v1/src/test/resources/testng.xml(1 hunks)pom.xml(5 hunks)
🧰 Additional context used
🧬 Code graph analysis (9)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (3)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
CredentialManagementConstants(29-149)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)
CredentialMgtClientException(26-62)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java (1)
CredentialMgtServerException(24-37)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
CredentialManagementConstants(29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
Builder(55-83)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (4)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
CredentialManagementConstants(29-149)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java (1)
PasskeyCredentialHandler(49-157)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (1)
PushCredentialHandler(46-122)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (1)
CredentialManagementServiceImpl(39-96)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (5)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
CredentialManagementConstants(29-149)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
CredentialDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
CredentialDeletionRequestDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
CredentialMgtException(24-97)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (1)
CredentialMgtEndpointUtils(43-185)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementService.java (2)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
CredentialDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
CredentialDeletionRequestDTO(24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
Builder(55-83)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java (6)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
CredentialManagementConstants(29-149)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java (1)
CredentialManagementServiceDataHolder(29-81)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
CredentialDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
CredentialDeletionRequestDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
CredentialMgtException(24-97)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (1)
CredentialManagementUtils(29-70)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (8)
components/org.wso2.carbon.identity.api.server.common/src/main/java/org/wso2/carbon/identity/api/server/common/error/APIError.java (1)
APIError(25-63)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
CredentialManagementConstants(29-149)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
CredentialDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)
CredentialMgtClientException(26-62)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
CredentialMgtException(24-97)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java (1)
CredentialMgtServerException(24-37)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/Credential.java (1)
Credential(33-175)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/constants/CredentialMgtEndpointConstants.java (1)
CredentialMgtEndpointConstants(24-68)
🪛 Checkov (3.2.334)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml
[medium] 50-54: Ensure that arrays have a maximum number of items
(CKV_OPENAPI_21)
🔇 Additional comments (22)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/pom.xml (1)
1-49: LGTM! Clean Maven module configuration.The POM structure is well-organized with appropriate dependencies for credential management functionality (identity core, FIDO2 authenticator, and push notification handler). Dependencies correctly rely on parent POM for version management.
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/pom.xml (1)
36-111: LGTM! Well-structured dependencies for REST API module.Dependencies are appropriately scoped with CXF for JAX-RS, comprehensive Jackson exclusions to avoid conflicts, and proper test framework setup with TestNG and Mockito.
components/org.wso2.carbon.identity.api.server.credential.management/pom.xml (1)
1-37: LGTM! Standard parent POM for multi-module structure.The parent POM correctly declares the common and v1 modules, establishing a clean multi-module project structure for the credential management feature.
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
55-83: LGTM! Well-implemented builder pattern.The builder provides a clean, fluent API for constructing immutable CredentialDeletionRequestDTO instances. Implementation follows standard builder pattern conventions.
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/constants/CredentialMgtEndpointConstants.java (1)
24-68: LGTM! Well-structured constants class.The constants class follows best practices with a private constructor to prevent instantiation, and the ErrorMessages enum provides a clean, type-safe approach to error code management. The
getCode()method correctly applies the common prefix to maintain consistency across all error codes.components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
24-84: LGTM! Properly implemented immutable DTO.The DTO correctly implements immutability with final fields and provides a clean builder pattern for construction. This serves as a good reference for the similar pattern used in
CredentialDeletionRequestDTO.pom.xml (1)
820-825: LGTM!The Maven configuration changes properly introduce the new credential management module with appropriate dependencies and scoping. The test dependency (mockito-testng), version properties (identity.local.auth.fido.version, identity.notification.push.version), dependency management entries, and module declaration are all correctly configured.
Also applies to: 865-880, 1014-1015, 1080-1080
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialHandler.java (1)
30-41: LGTM!The interface contract is clear and well-defined with appropriate exception declarations.
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java (1)
24-37: LGTM!The server exception class properly extends the base
CredentialMgtExceptionand provides a clean constructor for error context.components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)
26-62: LGTM!The client exception class provides convenient constructor overloads, including one that accepts
ErrorMessagesenum for standardized error handling.components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
60-80: Add documentation clarifying punctuation equivalence or restrict accepted input formats.The
fromStringmethod's use ofCollatorwithPRIMARYstrength correctly handles case-insensitive matching and whitespace trimming. Comprehensive test coverage confirms this works for "passkey", "PASSKEY", "PassKey", and similar variants, as well as leading/trailing spaces.However, the test data provider includes
"push_auth"(underscore) matching toPUSH_AUTH, despite the apiValue being"push-auth"(hyphen). This works becauseCollator.PRIMARYtreats punctuation as ignorable in many collation implementations, but this behavior is:
- Not documented in the code
- Not guaranteed by the Java specification
- Potentially fragile across different JDK versions
Either document this punctuation equivalence behavior explicitly (with comments explaining why "push_auth" and "push-auth" are equivalent), or restrict the comparison to enforce exact apiValue matching or enum name matching only, to avoid unexpected side effects.
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (1)
108-121: LGTM!The
mapPushToCredentialDTOhelper method is well-implemented with clear mapping logic from theDevicemodel toCredentialDTO.components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java (1)
125-132: LGTM!The
mapPasskeyToCredentialDTOmethod correctly maps FIDO2 credential fields to the DTO using the builder pattern.components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (1)
29-33: LGTM!Private constructor properly prevents instantiation of the utility class.
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
24-56: LGTM!The exception class is well-structured with proper constructor chaining, clear field encapsulation, and support for both root-cause and non-root-cause exception scenarios. The protected setters allow subclass flexibility while maintaining encapsulation.
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (4)
56-60: LGTM!The exception handling implementation is clean and delegates correctly to
getError.
105-112: LGTM!Clean error DTO construction with all required fields.
134-140: LGTM!Proper validation for credential ID with appropriate exception handling.
148-157: LGTM!Proper null/empty handling and clean stream-based conversion.
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (3)
66-78: LGTM!Clean test setup using reflection to inject dependencies. The use of
EnumMapfor handler mapping is type-safe and efficient.
83-249: LGTM!Comprehensive test coverage including success paths, empty results, exception handling, and partial failure scenarios. The tests properly validate fail-fast behavior and handler interaction patterns.
263-283: LGTM!Clean helper methods for creating test fixtures. Proper use of Mockito's mocking capabilities.
| if (LOG.isDebugEnabled()) { | ||
| LOG.info("Successfully retrieved " + credentialDTOs.size() + " passkey credentials for entity ID: " | ||
| + entityId); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect log level: LOG.info inside LOG.isDebugEnabled() check.
The condition checks for debug level but logs at info level.
if (LOG.isDebugEnabled()) {
- LOG.info("Successfully retrieved " + credentialDTOs.size() + " passkey credentials for entity ID: "
+ LOG.debug("Successfully retrieved " + credentialDTOs.size() + " passkey credentials for entity ID: "
+ entityId);
}🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java
around lines 76-79, the code checks LOG.isDebugEnabled() but calls
LOG.info(...); change the call to LOG.debug(...) so the logged level matches the
guard (or alternatively change the guard to LOG.isInfoEnabled() if info is
intended); ensure the log invocation uses the matching level and keep the same
message content.
| if (LOG.isDebugEnabled()) { | ||
| LOG.info("Successfully deleted passkey credential for entity ID: " | ||
| + credentialDeletionRequest.getEntityId()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect log level: LOG.info inside LOG.isDebugEnabled() check.
Same issue - the log statement should use LOG.debug to match the condition.
if (LOG.isDebugEnabled()) {
- LOG.info("Successfully deleted passkey credential for entity ID: "
+ LOG.debug("Successfully deleted passkey credential for entity ID: "
+ credentialDeletionRequest.getEntityId());
}📝 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.
| if (LOG.isDebugEnabled()) { | |
| LOG.info("Successfully deleted passkey credential for entity ID: " | |
| + credentialDeletionRequest.getEntityId()); | |
| } | |
| if (LOG.isDebugEnabled()) { | |
| LOG.debug("Successfully deleted passkey credential for entity ID: " | |
| credentialDeletionRequest.getEntityId()); | |
| } |
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java
around lines 100-103, the code checks LOG.isDebugEnabled() but calls
LOG.info(...) inside that block; change the call to LOG.debug(...) so the log
level matches the debug-enabled guard (or remove the guard if you prefer an
unconditional info log), keeping the message text the same.
| AbstractUserStoreManager userStoreManager = (AbstractUserStoreManager) userRealm | ||
| .getTenantUserRealm(IdentityTenantUtil.getTenantId(tenantDomain)).getUserStoreManager(); | ||
| return userStoreManager.getUserNameFromUserID(userId) + "@" + tenantDomain; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential null username could result in "null@tenantDomain".
If getUserNameFromUserID returns null (user not found), the concatenation produces an invalid username string. Consider validating the username before concatenation.
- return userStoreManager.getUserNameFromUserID(userId) + "@" + tenantDomain;
+ String username = userStoreManager.getUserNameFromUserID(userId);
+ if (username == null) {
+ throw new CredentialMgtException(
+ CredentialManagementConstants.ErrorMessages.ERROR_CODE_ENTITY_NOT_FOUND.getMessage(),
+ CredentialManagementConstants.ErrorMessages.ERROR_CODE_ENTITY_NOT_FOUND.getCode(),
+ String.format(CredentialManagementConstants.ErrorMessages.ERROR_CODE_ENTITY_NOT_FOUND.getDescription(), userId));
+ }
+ return username + "@" + tenantDomain;| public PushCredentialHandler() { | ||
|
|
||
| this.deviceHandler = CredentialManagementServiceDataHolder.getPushDeviceHandler(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Potential NPE if DeviceHandlerService is not initialized.
The deviceHandler obtained from CredentialManagementServiceDataHolder could be null if the OSGi service is not yet available when the handler is instantiated. Consider adding a null check or documenting the initialization requirements.
🏁 Script executed:
#!/bin/bash
# Check if CredentialManagementServiceDataHolder has null safety for getPushDeviceHandler
ast-grep --pattern $'public static DeviceHandlerService getPushDeviceHandler() {
$$$
}'Length of output: 1154
🏁 Script executed:
#!/bin/bash
# Find PushDeviceHandlerHolder and check SERVICE initialization
fd PushDeviceHandlerHolder --type f | head -5Length of output: 0
🏁 Script executed:
#!/bin/bash
# Check PushCredentialHandler for null checks on deviceHandler
rg -nA5 "this\.deviceHandler" components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.javaLength of output: 225
🏁 Script executed:
#!/bin/bash
# Look for null checks in PushCredentialHandler methods
rg -nB2 -A10 "public void\|public.*get" components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java | head -50Length of output: 0
🏁 Script executed:
#!/bin/bash
# Find the actual PushDeviceHandlerHolder class
find . -name "*PushDeviceHandlerHolder*" -type fLength of output: 0
🏁 Script executed:
#!/bin/bash
# Check CredentialManagementServiceDataHolder for SERVICE field initialization
rg -nB5 -A15 "class CredentialManagementServiceDataHolder\|class PushDeviceHandlerHolder" components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java | head -60Length of output: 0
🏁 Script executed:
#!/bin/bash
# View the complete CredentialManagementServiceDataHolder.java file
cat components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.javaLength of output: 2441
🏁 Script executed:
#!/bin/bash
# View the complete PushCredentialHandler.java file
cat components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.javaLength of output: 5782
🏁 Script executed:
#!/bin/bash
# Search for any null checks involving deviceHandler
rg "deviceHandler\s*==" components/org.wso2.carbon.identity.api.server.credential.management/ -A3 -B3Length of output: 0
Add null check for deviceHandler or guard against uninitialized OSGi service.
The deviceHandler obtained from CredentialManagementServiceDataHolder.getPushDeviceHandler() can be null if the DeviceHandlerService OSGi service is not available (line 45 in DataHolder calls getOSGiService() which returns null when service is not registered). Both getCredentials() (line 67) and deleteCredential() (line 83) invoke methods on deviceHandler without null checks, risking a NullPointerException at runtime. Add a null check in the constructor or guard each method call.
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java
around lines 52–55, the deviceHandler fetched from
CredentialManagementServiceDataHolder.getPushDeviceHandler() can be null when
the OSGi service is unregistered; add a null check and guard against
uninitialized service: either validate deviceHandler in the constructor and
throw an IllegalStateException with a clear message if null, or set a boolean
'enabled' flag and have getCredentials() and deleteCredential() check that flag
(or deviceHandler != null) before invoking methods, returning appropriate
error/empty responses when the service is unavailable.
| if (LOG.isDebugEnabled()) { | ||
| LOG.info("Successfully retrieved push authentication credential for entity ID: " + entityId); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect log level: LOG.info inside LOG.isDebugEnabled() check.
The condition checks for debug level but logs at info level. This is inconsistent and the info message will only appear when debug is enabled, which is likely unintended.
if (LOG.isDebugEnabled()) {
- LOG.info("Successfully retrieved push authentication credential for entity ID: " + entityId);
+ LOG.debug("Successfully retrieved push authentication credential for entity ID: " + entityId);
}📝 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.
| if (LOG.isDebugEnabled()) { | |
| LOG.info("Successfully retrieved push authentication credential for entity ID: " + entityId); | |
| } | |
| if (LOG.isDebugEnabled()) { | |
| LOG.debug("Successfully retrieved push authentication credential for entity ID: " + entityId); | |
| } |
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java
around lines 68 to 70, the code checks LOG.isDebugEnabled() but calls
LOG.info(...) which is inconsistent; change the log call to
LOG.debug("Successfully retrieved push authentication credential for entity ID:
" + entityId) so the message level matches the guard (or alternatively change
the guard to LOG.isInfoEnabled() if the intent is to keep an info-level
message).
| if (LOG.isDebugEnabled()) { | ||
| LOG.info("Successfully retrieved " + allCredentials.size() + " credentials."); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect log level: LOG.info inside LOG.isDebugEnabled() check.
The condition checks for debug level but logs at info level.
if (LOG.isDebugEnabled()) {
- LOG.info("Successfully retrieved " + allCredentials.size() + " credentials.");
+ LOG.debug("Successfully retrieved " + allCredentials.size() + " credentials.");
}📝 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.
| if (LOG.isDebugEnabled()) { | |
| LOG.info("Successfully retrieved " + allCredentials.size() + " credentials."); | |
| } | |
| if (LOG.isDebugEnabled()) { | |
| LOG.debug("Successfully retrieved " + allCredentials.size() + " credentials."); | |
| } |
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java
around lines 64 to 66, the code checks LOG.isDebugEnabled() but calls
LOG.info(...); change the logged method to LOG.debug(...) (or change the guard
to LOG.isInfoEnabled() if the intent is an info-level message) so the log level
and guard match; update only the log invocation or the guard accordingly to
ensure correct logging level.
| CredentialTypes credentialType = CredentialTypes.valueOf(credentialDeletionRequest.getType() | ||
| .replace("-", "_").toUpperCase(Locale.ROOT)); | ||
| CredentialHandler handler = handlerMap.get(credentialType); | ||
| handler.deleteCredential(credentialDeletionRequest); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential NPE if handler is not found in the map.
After converting the credential type string to CredentialTypes enum, handlerMap.get(credentialType) could return null if the handler isn't registered. The subsequent handler.deleteCredential() call would throw an NPE.
CredentialTypes credentialType = CredentialTypes.valueOf(credentialDeletionRequest.getType()
.replace("-", "_").toUpperCase(Locale.ROOT));
CredentialHandler handler = handlerMap.get(credentialType);
+ if (handler == null) {
+ throw new CredentialMgtException("Unsupported credential type",
+ "CM-60005", "No handler registered for credential type: " + credentialType);
+ }
handler.deleteCredential(credentialDeletionRequest);📝 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.
| CredentialTypes credentialType = CredentialTypes.valueOf(credentialDeletionRequest.getType() | |
| .replace("-", "_").toUpperCase(Locale.ROOT)); | |
| CredentialHandler handler = handlerMap.get(credentialType); | |
| handler.deleteCredential(credentialDeletionRequest); | |
| CredentialTypes credentialType = CredentialTypes.valueOf(credentialDeletionRequest.getType() | |
| .replace("-", "_").toUpperCase(Locale.ROOT)); | |
| CredentialHandler handler = handlerMap.get(credentialType); | |
| if (handler == null) { | |
| throw new CredentialMgtException("Unsupported credential type", | |
| "CM-60005", "No handler registered for credential type: " + credentialType); | |
| } | |
| handler.deleteCredential(credentialDeletionRequest); |
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/.../CredentialManagementServiceImpl.java
around lines 82-85, handlerMap.get(credentialType) can return null which leads
to an NPE on handler.deleteCredential(...); add a null check after retrieving
the handler and handle the missing handler case instead of calling
deleteCredential: if handler is null, log a clear message including the
credentialType and return/throw an appropriate API error (or a
CredentialManagement-specific exception) indicating the handler is not
registered; only call handler.deleteCredential(...) when handler != null. Ensure
the error path uses the service's existing error handling pattern (HTTP response
or typed exception) and include the credentialType in the message for easier
debugging.
| if (LOG.isDebugEnabled()) { | ||
| LOG.info("Successfully deleted credential type: " | ||
| + credentialDeletionRequest.getType() + " with ID: " | ||
| + credentialDeletionRequest.getCredentialId() + " for entity ID: " | ||
| + credentialDeletionRequest.getEntityId()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect log level: LOG.info inside LOG.isDebugEnabled() check.
Same issue - the log statement should use LOG.debug to match the condition.
if (LOG.isDebugEnabled()) {
- LOG.info("Successfully deleted credential type: "
+ LOG.debug("Successfully deleted credential type: "
+ credentialDeletionRequest.getType() + " with ID: "
+ credentialDeletionRequest.getCredentialId() + " for entity ID: "
+ credentialDeletionRequest.getEntityId());
}📝 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.
| if (LOG.isDebugEnabled()) { | |
| LOG.info("Successfully deleted credential type: " | |
| + credentialDeletionRequest.getType() + " with ID: " | |
| + credentialDeletionRequest.getCredentialId() + " for entity ID: " | |
| + credentialDeletionRequest.getEntityId()); | |
| } | |
| if (LOG.isDebugEnabled()) { | |
| LOG.debug("Successfully deleted credential type: " | |
| credentialDeletionRequest.getType() + " with ID: " | |
| credentialDeletionRequest.getCredentialId() + " for entity ID: " | |
| credentialDeletionRequest.getEntityId()); | |
| } |
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java
around lines 89 to 94, the log call inside a LOG.isDebugEnabled() check uses
LOG.info; change that to LOG.debug so the logging level matches the
debug-enabled guard, keeping the same message and string concatenation.
| code: | ||
| type: string | ||
| description: A unique, machine-readable error code following the WSO2 standard. | ||
| example: 'CM-60401' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify error code format consistency.
Line 161 shows example error code 'CM-60401', but CredentialManagementConstants.ErrorMessages defines codes like 'CM-60001', 'CM-60002', etc. Ensure the example uses a valid error code from the constants.
Run the following script to check all defined error codes:
🏁 Script executed:
#!/bin/bash
# Find all error code definitions in CredentialManagementConstants
ast-grep --pattern 'ERROR_CODE_$_(\"$_\", $_)'Length of output: 0
I need to search more broadly for the error code definitions. Let me try different approaches to locate the constants file and verify the error codes.
---
🏁 Script executed:
```shell
#!/bin/bash
# Find CredentialManagementConstants file
fd CredentialManagementConstants
Length of output: 247
🏁 Script executed:
#!/bin/bash
# Search for error code definitions with broader pattern
rg -n "CM-[0-9]+" --type=java -C2Length of output: 2503
🏁 Script executed:
#!/bin/bash
# Search for ERROR_CODE or error code patterns in Java files
rg -n "ERROR_CODE|ErrorMessages" --type=java -C1 | head -100Length of output: 25526
Let me examine the complete CredentialManagementConstants file to confirm all defined error codes:
---
🏁 Script executed:
```shell
#!/bin/bash
# View the CredentialManagementConstants.java ErrorMessages enum
cat components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java | grep -A 50 "public enum ErrorMessages"
Length of output: 2472
Update example error code to use a valid constant from CredentialManagementConstants.ErrorMessages.
The example 'CM-60401' does not exist. Valid error codes are CM-65001, CM-65002, CM-65003, CM-65004 (server errors) or CM-60001 through CM-60006 (client errors). Use one of these, such as 'CM-60001'.
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml
around lines 158 to 161, the example error code 'CM-60401' is invalid; replace
it with a valid constant from CredentialManagementConstants.ErrorMessages such
as 'CM-60001' (or any of CM-65001..CM-65004 or CM-60001..CM-60006) so the
example matches an actual defined error code.
| @DataProvider(name = "edgeCaseInputs") | ||
| public Object[][] edgeCaseInputs() { | ||
|
|
||
| return new Object[][]{ | ||
| {" passkey ", CredentialTypes.PASSKEY}, | ||
| {"PassKey", CredentialTypes.PASSKEY} | ||
| }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Remove unused data provider.
The edgeCaseInputs data provider is defined but not used by any test method. This is dead code.
Either remove it or add a corresponding test method:
- @DataProvider(name = "edgeCaseInputs")
- public Object[][] edgeCaseInputs() {
-
- return new Object[][]{
- {" passkey ", CredentialTypes.PASSKEY},
- {"PassKey", CredentialTypes.PASSKEY}
- };
- }Alternatively, if edge-case testing is intended, add a test method that uses this provider:
@Test(dataProvider = "edgeCaseInputs")
public void testDeleteCredentialWithEdgeCaseInputs(String typeInput, CredentialTypes expectedType)
throws CredentialMgtException {
// Test implementation
}🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java
around lines 251 to 258, the DataProvider method edgeCaseInputs is defined but
never referenced, making it dead code; either remove this unused DataProvider or
add a test method annotated with @Test(dataProvider = "edgeCaseInputs") that
consumes the two inputs (e.g., trimming/case-insensitive credential type
parsing) and asserts the expected CredentialTypes so the provider is utilized.
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/UsersCredentialApiServiceImpl.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/resources/testng.xml(1 hunks)
🔇 Additional comments (3)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/resources/testng.xml (2)
1-20: License and XML structure look good.The Apache 2.0 license header is properly formatted, and the XML structure is valid and follows TestNG conventions.
21-27: Repository access unavailable; manual verification required.I was unable to access the repository to verify the concerns raised in the original review comment. The repository clone operation failed, preventing me from:
- Confirming the test class file exists at the specified fully qualified name
- Verifying the package declaration in the test class
- Examining the module structure to assess naming consistency
- Comparing with other TestNG suite configurations in the project
The original review's concerns about the suite name including "common" while the test class resides in the "v1.impl" module remain valid but unverified. The suite naming convention requires manual inspection of the codebase to determine if this is:
- An intentional organizational choice, or
- A naming inconsistency that should be corrected
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/UsersCredentialApiServiceImpl.java (1)
37-47: I was unable to clone the WSO2 Identity API Server repository to verify the specific implementation details. However, based on WSO2 best practices from the web search:Key findings from WSO2 patterns:
- JAX-RS services should use centralized exception mappers (with
@Providerannotation) rather than inline error handling- Input validation can be applied via Bean Validation framework (
@Valid,@NotNull, etc.) at the parameter level- Error handling and logging are typically centralized and not inline in service methods
- Services should delegate to exception mappers for HTTP response generation
Without access to the codebase, I cannot verify:
- Whether exception mappers are already implemented for credential deletion errors
- Whether validation annotations are applied to method parameters
- Whether a centralized logging/auditing mechanism exists for sensitive operations
- How similar credential operations are implemented in the same service class
Since the repository is not publicly accessible and verification is inconclusive, here is the rewritten review comment:
Verify input validation and error handling strategy are implemented centrally.
This method lacks visible input validation for
userId,type, andcredentialId. According to WSO2 best practices, validate these parameters early—either via Bean Validation annotations (@NotNull,@NotEmpty) on method parameters or through a centralized validation layer. Confirm that exceptions fromdeleteCredential()are handled by a global JAX-RS exception mapper (annotated@Provider) and that credential deletion operations are logged for audit purposes.
| private final CredentialManagementService credentialManagementService = | ||
| CredentialManagementServiceFactory.getCredentialManagementService(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add null safety check for service initialization.
If CredentialManagementServiceFactory.getCredentialManagementService() returns null, all method calls will throw a NullPointerException at runtime.
Add a null check or defensive initialization:
private final CredentialManagementService credentialManagementService =
CredentialManagementServiceFactory.getCredentialManagementService();
+
+ public UsersCredentialApiServiceImpl() {
+ if (credentialManagementService == null) {
+ throw new IllegalStateException("CredentialManagementService is not available");
+ }
+ }📝 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.
| private final CredentialManagementService credentialManagementService = | |
| CredentialManagementServiceFactory.getCredentialManagementService(); | |
| private final CredentialManagementService credentialManagementService = | |
| CredentialManagementServiceFactory.getCredentialManagementService(); | |
| public UsersCredentialApiServiceImpl() { | |
| if (credentialManagementService == null) { | |
| throw new IllegalStateException("CredentialManagementService is not available"); | |
| } | |
| } |
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/.../UsersCredentialApiServiceImpl.java
around lines 34-35, the direct call to
CredentialManagementServiceFactory.getCredentialManagementService() can return
null and cause NPEs; change the initialization to handle null by adding a
defensive check: if the factory returns null, either assign a clear
no-op/placeholder implementation or throw a descriptive IllegalStateException
(or log and propagate a 500-level API error) so subsequent method calls never
operate on a null service; ensure all usages assume non-null and update
constructors or getters accordingly to enforce this invariant.
| @Override | ||
| public Response getUserCredentialsById(String userId) { | ||
|
|
||
| return Response.ok() | ||
| .entity(CredentialMgtEndpointUtils | ||
| .toCredentialResponse(credentialManagementService.getCredentials(userId))) | ||
| .build(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add input validation for userId parameter.
The userId parameter is not validated before use. A null value will cause a NullPointerException when passed to getCredentials().
Add validation:
@Override
public Response getUserCredentialsById(String userId) {
-
+ if (userId == null || userId.trim().isEmpty()) {
+ throw new IllegalArgumentException("userId cannot be null or empty");
+ }
+
return Response.ok()
.entity(CredentialMgtEndpointUtils
.toCredentialResponse(credentialManagementService.getCredentials(userId)))
.build();
}📝 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.
| @Override | |
| public Response getUserCredentialsById(String userId) { | |
| return Response.ok() | |
| .entity(CredentialMgtEndpointUtils | |
| .toCredentialResponse(credentialManagementService.getCredentials(userId))) | |
| .build(); | |
| } | |
| @Override | |
| public Response getUserCredentialsById(String userId) { | |
| if (userId == null || userId.trim().isEmpty()) { | |
| throw new IllegalArgumentException("userId cannot be null or empty"); | |
| } | |
| return Response.ok() | |
| .entity(CredentialMgtEndpointUtils | |
| .toCredentialResponse(credentialManagementService.getCredentials(userId))) | |
| .build(); | |
| } |
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/UsersCredentialApiServiceImpl.java
around lines 49 to 56, the userId parameter is used without validation which can
cause a NullPointerException; add an input check that returns a 400 Bad Request
(or appropriate API error Response) when userId is null or empty before calling
credentialManagementService.getCredentials(userId), and only call getCredentials
and build the OK response when the validation passes.
8c8ea7f to
c8f9d9e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (10)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
99-102: Double spaces in error descriptions.Lines 100 and 102 contain double spaces before "was" (
%s was). Remove the extra space for clean error messages.ERROR_CODE_DELETE_PASSKEY_CREDENTIAL("60001", "Error deleting credential.", - "The request to delete the passkey credential: %s was invalid."), + "The request to delete the passkey credential: %s was invalid."), ERROR_CODE_DELETE_PUSH_AUTH_CREDENTIAL("60002", "Error deleting credential.", - "The request to delete the push auth credential: %s was invalid."), + "The request to delete the push auth credential: %s was invalid."),components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
26-28: Declare fields as final for immutability.The fields should be
finalto ensure immutability and thread safety, consistent with the pattern used inCredentialDTO.java.Apply this diff:
- private String entityId; - private String credentialId; - private String type; + private final String entityId; + private final String credentialId; + private final String type;components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml (1)
161-161: Invalid error code in example.The example error code 'CM-60401' does not match any defined constant in
CredentialManagementConstants.ErrorMessages. Valid codes are CM-65001 through CM-65004 (server errors) or CM-60001 through CM-60006 (client errors).Apply this diff to use a valid error code:
- example: 'CM-60401' + example: 'CM-60001'components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (3)
64-66: Incorrect log level inside debug guard.The condition checks
LOG.isDebugEnabled()but logs at info level, which is inconsistent.Apply this diff:
if (LOG.isDebugEnabled()) { - LOG.info("Successfully retrieved " + allCredentials.size() + " credentials."); + LOG.debug("Successfully retrieved " + allCredentials.size() + " credentials."); }
82-85: Potential NullPointerException: missing null check for handler.
handlerMap.get(credentialType)can return null if no handler is registered for the credential type. The subsequent call tohandler.deleteCredential()will throw an NPE.Apply this diff to add a null check:
CredentialTypes credentialType = CredentialTypes.valueOf(credentialDeletionRequest.getType() .replace("-", "_").toUpperCase(Locale.ROOT)); CredentialHandler handler = handlerMap.get(credentialType); + if (handler == null) { + throw new CredentialMgtException("Unsupported credential type", + CredentialManagementConstants.ErrorMessages.ERROR_CODE_INVALID_CREDENTIAL_TYPE.getCode(), + "No handler registered for credential type: " + credentialType); + } handler.deleteCredential(credentialDeletionRequest);
89-94: Incorrect log level inside debug guard.Same issue -
LOG.infois used inside aLOG.isDebugEnabled()check.Apply this diff:
if (LOG.isDebugEnabled()) { - LOG.info("Successfully deleted credential type: " + LOG.debug("Successfully deleted credential type: " + credentialDeletionRequest.getType() + " with ID: " + credentialDeletionRequest.getCredentialId() + " for entity ID: " + credentialDeletionRequest.getEntityId()); }components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (3)
52-55: Potential NullPointerException: deviceHandler can be null.The
deviceHandlerobtained fromCredentialManagementServiceDataHolder.getPushDeviceHandler()can return null if the OSGi service is not available. BothgetCredentials()anddeleteCredential()will fail with an NPE if the service is unregistered.Add a null check in the constructor:
public PushCredentialHandler() { this.deviceHandler = CredentialManagementServiceDataHolder.getPushDeviceHandler(); + if (this.deviceHandler == null) { + throw new IllegalStateException("DeviceHandlerService is not available. " + + "Ensure the push device handler OSGi service is registered."); + } }
68-70: Incorrect log level inside debug guard.The condition checks
LOG.isDebugEnabled()but logs at info level.Apply this diff:
if (LOG.isDebugEnabled()) { - LOG.info("Successfully retrieved push authentication credential for entity ID: " + entityId); + LOG.debug("Successfully retrieved push authentication credential for entity ID: " + entityId); }
94-97: Incorrect log level inside debug guard.Same issue -
LOG.infois used inside aLOG.isDebugEnabled()check.Apply this diff:
if (LOG.isDebugEnabled()) { - LOG.info("Successfully deleted push authentication credential for entity ID: " + LOG.debug("Successfully deleted push authentication credential for entity ID: " + credentialDeletionRequest.getEntityId()); }components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (1)
251-258: Remove or use the unusededgeCaseInputsdata provider
edgeCaseInputsis still not referenced by any@Testmethod, so it remains dead code. Either remove this provider or add a test (e.g., anotherdeleteCredentialtest using@Test(dataProvider = "edgeCaseInputs")) that exercises trimming and mixed‑case inputs.
🧹 Nitpick comments (12)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (2)
60-80: Consider simplifying withequalsIgnoreCaseinstead ofCollator.The
CollatorwithPRIMARYstrength is more robust for Unicode edge cases, but for matching simple ASCII enum names like "passkey" and "push-auth",String.equalsIgnoreCase()would be simpler and more readable.- Collator collator = Collator.getInstance(Locale.ROOT); - collator.setStrength(Collator.PRIMARY); - - return Arrays.stream(values()) - .filter(type -> collator.compare(type.name(), candidate) == 0 - || collator.compare(type.getApiValue(), candidate) == 0) - .findFirst(); + return Arrays.stream(values()) + .filter(type -> type.name().equalsIgnoreCase(candidate) + || type.getApiValue().equalsIgnoreCase(candidate)) + .findFirst();
115-116: Consider relocating external error code constant.
ERROR_CODE_PUSH_AUTH_DEVICE_NOT_FOUNDis a raw string constant (from Push Device Handler service) that doesn't follow theErrorMessagesenum pattern. Placing it inside the enum is unconventional and could cause confusion.Move it to the enclosing class as a class-level constant:
public class CredentialManagementConstants { + public static final String ERROR_CODE_PUSH_AUTH_DEVICE_NOT_FOUND = "PDH-15010"; + private CredentialManagementConstants() { }Then remove it from inside the
ErrorMessagesenum:- public static final String ERROR_CODE_PUSH_AUTH_DEVICE_NOT_FOUND = "PDH-15010"; private final String code;components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialHandler.java (2)
31-34: Consider enhancing the method javadoc.The javadoc could be more comprehensive for this public API method. Consider documenting the parameter meaning, return value semantics (e.g., whether an empty list is returned when no credentials exist), and the conditions under which
CredentialMgtExceptionis thrown.Example enhancement:
/** - * Retrieves credentials for a given entity. + * Retrieves all credentials of this type for a given entity. + * + * @param entityId the unique identifier of the entity (e.g., user ID) + * @return a list of credentials, or an empty list if none exist + * @throws CredentialMgtException if retrieval fails due to backend errors */
36-40: Consider enhancing the method javadoc.Similar to
getCredentials, the javadoc could provide more detail about the parameter requirements and exception conditions for better API clarity.Example enhancement:
/** - * Deletes a credential for an entity. + * Deletes a specific credential for an entity. + * + * @param credentialDeletionRequest the deletion request containing entity and credential identifiers + * @throws CredentialMgtException if deletion fails or the credential does not exist */components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (2)
33-34: Add private constructor to prevent instantiation.Utility/factory classes with only static methods should have a private constructor to prevent instantiation and clearly communicate intent.
Apply this diff:
public class CredentialManagementServiceFactory { + + private CredentialManagementServiceFactory() { + // Prevent instantiation + }
35-41: Consider caching the service instance if called frequently.The factory creates new handler instances on every invocation. If
getCredentialManagementService()is called repeatedly, consider caching either the handlers or the entire service instance to improve efficiency.Example with lazy singleton pattern:
private static volatile CredentialManagementServiceImpl instance; public static CredentialManagementServiceImpl getCredentialManagementService() { if (instance == null) { synchronized (CredentialManagementServiceFactory.class) { if (instance == null) { Map<CredentialTypes, CredentialHandler> handlerMap = new EnumMap<>(CredentialTypes.class); handlerMap.put(CredentialTypes.PASSKEY, new PasskeyCredentialHandler()); handlerMap.put(CredentialTypes.PUSH_AUTH, new PushCredentialHandler()); instance = new CredentialManagementServiceImpl(handlerMap); } } } return instance; }components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/resources/testng.xml (1)
21-26: Suite name namespace doesn’t match module pathThe suite is named
...credential.management.commonwhile it lives under the.v1module and only runs...credential.management.v1.impl.CredentialManagementServiceImplTest. For clarity when multiple suites coexist, consider renaming the suite to reflect the v1 module (e.g.,...credential.management.v1).components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (5)
55-78: Test setup uses reflection on a mocked service – consider simplifyingUsing a
@MockforCredentialManagementServiceImpland injectinghandlerMapvia reflection works but is brittle against internal field or wiring changes. If possible, prefer a real instance (or@InjectMocks) with handlers injected via constructor / setter / package-private mutator so the tests exercise the object in a more realistic configuration.
145-158: Optionally assert APIError contents when a handler failsThe test currently only checks that an
APIErroris thrown. For stronger coverage of the exception mapping, consider capturing the thrownAPIError(e.g., viaAssert.expectThrows) and asserting its status and error code derived from theCredentialMgtException.
196-215: StrengthendeleteCredentialtest by asserting only the resolved handler is invokedRight now you verify that the expected handler is invoked once, but the test would still pass if both handlers were called. To guard against accidental double‑deletes, you can also assert that the non‑selected handler is never invoked:
- CredentialHandler expectedHandler = expectedType == CredentialTypes.PASSKEY ? - passkeyHandler : pushAuthHandler; - verify(expectedHandler, times(1)).deleteCredential(userCredentialDeletionRequest); + CredentialHandler expectedHandler = expectedType == CredentialTypes.PASSKEY ? + passkeyHandler : pushAuthHandler; + CredentialHandler unexpectedHandler = expectedType == CredentialTypes.PASSKEY ? + pushAuthHandler : passkeyHandler; + + verify(expectedHandler, times(1)).deleteCredential(userCredentialDeletionRequest); + verify(unexpectedHandler, never()).deleteCredential(userCredentialDeletionRequest);
217-230: Invalid credential‑type path is covered; consider checking error detailsThe test exercises the invalid credential type path and expects an
APIError, which is good. Optionally, you could assert the specific error code/message to ensure the endpoint surfaces the intended client error for unsupported types.
260-283: Consider using real DTO builders instead of mocked DTOs in helpersThe helper methods currently return Mockito‑mocked
CredentialDTO/CredentialDeletionRequestDTOinstances. Since these DTOs already provide builders, you could construct real instances instead, reducing mocking surface area and giving compile‑time feedback if DTO fields change. This is purely an optional test‑design improvement.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/Credential.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/Error.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/UsersApi.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/UsersApiService.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/UsersApiServiceFactory.javais excluded by!**/gen/**
📒 Files selected for processing (24)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/pom.xml(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialHandler.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementService.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/pom.xml(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/constants/CredentialMgtEndpointConstants.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/UsersCredentialApiServiceImpl.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/resources/testng.xml(1 hunks)components/org.wso2.carbon.identity.api.server.credential.management/pom.xml(1 hunks)pom.xml(5 hunks)
✅ Files skipped from review due to trivial changes (1)
- components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java
🚧 Files skipped from review as they are similar to previous changes (11)
- components/org.wso2.carbon.identity.api.server.credential.management/pom.xml
- components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java
- components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java
- components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/constants/CredentialMgtEndpointConstants.java
- components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/pom.xml
- components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java
- components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementService.java
- components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java
- components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java
- components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/UsersCredentialApiServiceImpl.java
- components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java
🧰 Additional context used
🧬 Code graph analysis (6)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (4)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
CredentialManagementConstants(29-149)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java (1)
PasskeyCredentialHandler(49-157)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (1)
PushCredentialHandler(46-122)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (1)
CredentialManagementServiceImpl(39-96)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (6)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
CredentialManagementConstants(29-149)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java (1)
CredentialManagementServiceDataHolder(29-81)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
CredentialDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
CredentialDeletionRequestDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
CredentialMgtException(24-97)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (1)
CredentialManagementUtils(29-70)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
Builder(55-83)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (4)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
CredentialManagementConstants(29-149)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
CredentialDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
CredentialDeletionRequestDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
CredentialMgtException(24-97)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
CredentialManagementConstants(29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (5)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
CredentialManagementConstants(29-149)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
CredentialDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
CredentialDeletionRequestDTO(24-84)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
CredentialMgtException(24-97)components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (1)
CredentialMgtEndpointUtils(43-185)
🪛 Checkov (3.2.334)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml
[medium] 50-54: Ensure that arrays have a maximum number of items
(CKV_OPENAPI_21)
🔇 Additional comments (12)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (1)
38-39: I'll help you verify the backend service initialization concerns. Let me search for the relevant code to understand the service initialization pattern and null safety.
<function_calls>
#!/bin/bashFind the CredentialManagementServiceDataHolder and handler implementations
fd -t f -name "*.java" | head -30
</function_calls>Let me get a better overview of the project structure:
<function_calls>
#!/bin/bashSearch for the DataHolder class
rg -n "class CredentialManagementServiceDataHolder" --type=java
</function_calls>Now let me search for the handler implementations:
<function_calls>
#!/bin/bashSearch for handler classes
rg -n "class PasskeyCredentialHandler|class PushCredentialHandler" --type=java
</function_calls>Let me also check the factory file itself to understand the context better:
<function_calls>
#!/bin/bashFind and examine the factory file
fd -t f -name "CredentialManagementServiceFactory.java" -exec cat -n {} ;
</function_calls>Let me search more broadly for these components:
<function_calls>
#!/bin/bashSearch for all references to DataHolder methods
rg -n "getWebAuthnService|getPushDeviceHandler" --type=java
</function_calls>Let me also check for OSGi component and service reference annotations:
<function_calls>
#!/bin/bashSearch for @component and @reference annotations
rg -n "@component|@reference|@service" --type=java | head -50
#!/bin/bash # List files to understand repository structure find . -type f -name "*.java" | grep -i "credential\|factory\|handler\|dataholder" | head -20
</function_calls>components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/pom.xml (1)
35-48: LGTM!Module structure is well-organized and dependency declarations follow Maven best practices. Version inheritance from parent dependencyManagement is correct.
pom.xml (3)
1014-1017: Clarify documentation inconsistency in version property comment.Line 1017 comment was changed to "Organization management impl Version" but the property name on line 1018 is
.core.version. The comment now mismatches the property it describes. Verify if this comment change was intentional or should be reverted/aligned with the actual property's purpose.
1080-1080: LGTM!Credential management module is properly registered in the modules list, maintaining alphabetical organization patterns in the module registry.
820-825: mockito-testng 0.5.2 is available in Maven Central but version mismatch with TestNG 6.9.10 warrants attention.mockito-testng version 0.5.2 is published to Maven Central and does not enforce a specific TestNG version, so it will technically run with TestNG 6.9.10. However, 0.5.2 was released in 2023 and is intended for modern TestNG releases. Using a significantly older TestNG version (6.9.10) may lead to API or behavior compatibility issues. Consider testing the combination or updating to a more recent TestNG version if runtime issues occur.
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)
19-27: Overall exception structure and ErrorMessages integration look goodThe class cleanly extends the base
CredentialMgtExceptionand theErrorMessages-based constructor keeps client errors aligned with the shared constants. No functional issues spotted here.Also applies to: 53-61
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (6)
80-103: Happy‑path aggregation ingetCredentialsis well coveredThis test cleanly verifies aggregation across both handlers and asserts the combined result plus interaction counts. No issues spotted here.
105-121: Empty‑result behavior is correctly assertedYou explicitly assert a non‑null but empty list and verify both handlers are invoked once, which is a good contract for the “no credentials” case.
123-143: Single‑handler success scenario looks correctThe case where only one handler returns credentials is exercised, and you still verify both handlers are called once; this nicely guards against silently skipping one of the handlers.
160-181: Short‑circuiting semantics on handler failure are well testedVerifying that the push‑auth handler is never called when the passkey handler fails gives good protection against partial‑success behavior sneaking in later. This test looks solid.
183-194: Credential type data provider covers key normalizationsThe
validCredentialTypesdata set nicely exercises case differences and both hyphen/underscore representations, which will catch regressions inCredentialTypesnormalization.
232-249: Exception propagation fordeleteCredentialis tested appropriatelyThis test verifies that a handler‑level
CredentialMgtExceptionduring deletion is mapped to anAPIError, which is the critical behavior here. No changes needed.
| /** | ||
| * Credential Management Service interface. | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct the interface javadoc.
The javadoc describes this as "Credential Management Service interface" but the interface is actually named CredentialHandler. The documentation should accurately reflect the interface name.
Apply this diff to fix the javadoc:
/**
- * Credential Management Service interface.
+ * Interface for handling credential operations for a specific credential type.
*/📝 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.
| /** | |
| * Credential Management Service interface. | |
| */ | |
| /** | |
| * Interface for handling credential operations for a specific credential type. | |
| */ |
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialHandler.java
around lines 27 to 29, update the class-level Javadoc so it accurately names the
interface (replace "Credential Management Service interface." with a description
that references the interface name, e.g., "CredentialHandler interface." or
"Interface for handling credential management operations."). Ensure the first
sentence references CredentialHandler and keep the Javadoc concise and
grammatically correct.
| /** | ||
| * Constructor with {@code message}, {@code errorCode} and {@code description} parameters. | ||
| * | ||
| * @param message Message to be included in the exception. | ||
| * @param errorCode Error code of the exception. | ||
| * @param description Description of the exception. | ||
| */ | ||
| public CredentialMgtClientException(String errorCode, String message, String description) { | ||
|
|
||
| super(message, errorCode, description); | ||
| } | ||
|
|
||
| /** | ||
| * Constructor with {@code message}, {@code errorCode}, {@code description} and {@code cause} parameters. | ||
| * | ||
| * @param message Message to be included in the exception. | ||
| * @param errorCode Error code of the exception. | ||
| * @param description Description of the exception. | ||
| * @param cause Exception to be wrapped. | ||
| */ | ||
| public CredentialMgtClientException(String errorCode, String message, String description, Throwable cause) { | ||
|
|
||
| super(message, errorCode, description, cause); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Constructor parameter order vs Javadoc is inconsistent and can confuse callers
Both String-based constructors take (String errorCode, String message, String description[, Throwable cause]), but the Javadoc text and @param tags describe the parameters in the order (message, errorCode, description, cause), while super(...) is called as (message, errorCode, description[, cause]). This mismatch is easy to misread and could lead to callers swapping arguments unintentionally.
Consider either:
- Updating the Javadoc (summary sentence and
@paramorder) to match the current signature, or - Reordering the parameters in the signature to
(String message, String errorCode, String description[, Throwable cause])for clarity and alignment with thesuper(...)call and docs.
Minimal fix (docs-only) example:
- /**
- * Constructor with {@code message}, {@code errorCode} and {@code description} parameters.
- *
- * @param message Message to be included in the exception.
- * @param errorCode Error code of the exception.
- * @param description Description of the exception.
- */
- public CredentialMgtClientException(String errorCode, String message, String description) {
+ /**
+ * Constructor with {@code errorCode}, {@code message} and {@code description} parameters.
+ *
+ * @param errorCode Error code of the exception.
+ * @param message Message to be included in the exception.
+ * @param description Description of the exception.
+ */
+ public CredentialMgtClientException(String errorCode, String message, String description) {
@@
- /**
- * Constructor with {@code message}, {@code errorCode}, {@code description} and {@code cause} parameters.
- *
- * @param message Message to be included in the exception.
- * @param errorCode Error code of the exception.
- * @param description Description of the exception.
- * @param cause Exception to be wrapped.
- */
- public CredentialMgtClientException(String errorCode, String message, String description, Throwable cause) {
+ /**
+ * Constructor with {@code errorCode}, {@code message}, {@code description} and {@code cause} parameters.
+ *
+ * @param errorCode Error code of the exception.
+ * @param message Message to be included in the exception.
+ * @param description Description of the exception.
+ * @param cause Exception to be wrapped.
+ */
+ public CredentialMgtClientException(String errorCode, String message, String description, Throwable cause) {🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/.../CredentialMgtClientException.java
around lines 28-51, the Javadoc describes parameters in the order (message,
errorCode, description, cause) while the constructors' signature is (String
errorCode, String message, String description[, Throwable cause]) and super(...)
is invoked as (message, errorCode, description[, cause]); update the Javadoc to
reflect the actual parameter order by changing the summary sentence and the
@param tags to list @param errorCode, @param message, @param description and
@param cause (in that order) with the correct descriptions so docs match the
signature and avoid confusion.
| <dependency> | ||
| <groupId>org.wso2.carbon.identity.server.api</groupId> | ||
| <artifactId>org.wso2.carbon.identity.api.server.credential.management.common</artifactId> | ||
| <version>${project.version}</version> | ||
| <scope>provided</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.wso2.carbon.identity.notification.push</groupId> | ||
| <artifactId>org.wso2.carbon.identity.notification.push.device.handler</artifactId> | ||
| <version>${identity.notification.push.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.wso2.carbon.identity.local.auth.fido</groupId> | ||
| <artifactId>org.wso2.carbon.identity.application.authenticator.fido2</artifactId> | ||
| <version>${identity.local.auth.fido.version}</version> | ||
| </dependency> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Script executed:
#!/bin/bash
# Verify artifact versions in repositories
echo "=== Checking artifact availability ==="
# Check fido2 authenticator (5.4.26) in Maven Central
echo -e "\n1. Checking fido2 authenticator v5.4.26:"
curl -s -w "\nHTTP Status: %{http_code}\n" \
"https://repo.maven.apache.org/maven2/org/wso2/carbon/identity/local/auth/fido/org.wso2.carbon.identity.application.authenticator.fido2/5.4.26/" | head -5
# Check push device handler (1.0.6) in Maven Central
echo -e "\n2. Checking push device handler v1.0.6:"
curl -s -w "\nHTTP Status: %{http_code}\n" \
"https://repo.maven.apache.org/maven2/org/wso2/carbon/identity/notification/push/org.wso2.carbon.identity.notification.push.device.handler/1.0.6/" | head -5
# Check credential management common artifact (uses ${project.version})
echo -e "\n3. Checking credential management common (uses project.version):"
curl -s -w "\nHTTP Status: %{http_code}\n" \
"https://repo.maven.apache.org/maven2/org/wso2/carbon/identity/server/api/org.wso2.carbon.identity.api.server.credential.management.common/" | head -5Repository: wso2/identity-api-server
<shell_result>
Repository: wso2/identity-api-server
Script execution failed with unrecoverable error: [CAPABILITY:RUN_SHELL_SCRIPT] Failed to clone repository wso2/identity-api-server: Clone operation failed
</shell_result>
org.wso2.carbon.identity.application.authenticator.fido2 5.4.26 Maven Central
<web_search_result>
I couldn't find an artifact with groupId org.wso2.carbon.identity.application.authenticator.fido2 version 5.4.26 on Maven Central. The FIDO2 authenticator artifacts are published under groupId org.wso2.carbon.identity.local.auth.fido (artifactId org.wso2.carbon.identity.application.authenticator.fido2) and available from the WSO2 repositories; known published versions include 5.3.x and 5.4.x (e.g. 5.3.32, 5.4.10 / 5.4.17), but not 5.4.26. [1][2]
Sources:
- org.wso2.carbon.identity.application.authenticator.fido2 (examples of published versions; WSO2 repo / mvnrepository). [1]
- org.wso2.carbon.identity.application.authenticator.fido2.server.feature (shows 5.4.x series; WSO2/Maven listings). [2]
</web_search_result>
org.wso2.carbon.identity.notification.push.device.handler 1.0.6 Maven Central
<web_search_result>
Yes — org.wso2.carbon.identity.notification.push.device.handler version 1.0.6 is published (available from WSO2 Releases). See the artifact listing and versions on MVNRepository. [1][2]
Maven dependency (use WSO2 Releases repository):
org.wso2.carbon.identity.notification.push
org.wso2.carbon.identity.notification.push.device.handler
1.0.6
Sources:
- Artifact page (versions list) — MVNRepository. [1]
- Related push-notification feature / provider v1.0.6 entries — MVNRepository. [2]
References:
[1] https://mvnrepository.com/artifact/org.wso2.carbon.identity.notification.push/org.wso2.carbon.identity.notification.push.device.handler
[2] https://mvnrepository.com/artifact/org.wso2.carbon.identity.notification.push/org.wso2.carbon.identity.notification.push.feature
</web_search_result>
WSO2 identity-notification-push device handler version 1.0.6
<web_search_result>
Yes — version 1.0.6 of the WSO2 push notification modules is available on Maven (released Feb 20, 2025). Maven coordinates you can use:
- GroupId: org.wso2.carbon.identity.notification.push
- ArtifactId: org.wso2.carbon.identity.notification.push.device.handler
- Version: 1.0.6. (mvnrepository.com)
The push feature/pom (identity-notification-push) also has a 1.0.6 release on WSO2 Maven listings. (mvnrepository.com)
If you want direct download or pom/bundle files, fetch them from the WSO2 Releases repository on the Maven pages above. (mvnrepository.com)
Citations:
- 1: https://mvnrepository.com/artifact/org.wso2.carbon.identity.notification.push/org.wso2.carbon.identity.notification.push.device.handler?utm_source=openai
- 2: https://mvnrepository.com/artifact/org.wso2.carbon.identity.notification.push/identity-notification-push/1.0.0?utm_source=openai
- 3: https://mvnrepository.com/artifact/org.wso2.carbon.identity.notification.push/org.wso2.carbon.identity.notification.push.device.handler?utm_source=openai
</web_search_result>
Verify FIDO2 authenticator version 5.4.26—this version may not exist in repositories.
The fido2 authenticator version 5.4.26 does not appear in known repositories. Available versions in the 5.4.x series are 5.4.10, 5.4.17, etc., but not 5.4.26. Confirm the correct version for org.wso2.carbon.identity.application.authenticator.fido2 or update the ${identity.local.auth.fido.version} property accordingly. The push device handler v1.0.6 is valid and published.
🤖 Prompt for AI Agents
In pom.xml around lines 865 to 880 the configured FIDO2 authenticator version
(${identity.local.auth.fido.version}) resolves to 5.4.26 which is not present in
known repositories; verify the correct published version for
org.wso2.carbon.identity.application.authenticator.fido2 and update the property
(or hardcode the dependency version) to a valid released version (e.g., 5.4.17
or whichever is found in your artifact repository), or if 5.4.26 is required
ensure it is published to your repo and update repository settings accordingly.
This pull request introduces a new common module for credential management in the WSO2 Identity Server API, providing foundational interfaces, DTOs, constants, and exception handling for credential management operations. The changes establish a clear contract for handling different credential types (such as passkeys and push authentication), standardize error handling, and facilitate integration with relevant backend services.
Key additions and changes include:
Core Interfaces and DTOs
CredentialManagementServiceandCredentialHandlerinterfaces, defining methods for retrieving and deleting user credentials, and introduced theCredentialDTOclass for transferring credential data. [1] [2] [3]Constants and Credential Types
CredentialManagementConstants, which defines supported credential types (e.g., passkey, push-auth) and standardized error messages for both server and client errors.Exception Handling Framework
CredentialMgtExceptionand specialized client and server exceptions (CredentialMgtClientException,CredentialMgtServerException). [1] [2] [3]Service Integration
CredentialManagementServiceDataHolderto provide access to backend services (e.g., WebAuthn and Push Device Handler) required for credential operations.Build Configuration
pom.xmlfor the common module, specifying dependencies on required WSO2 and test libraries.## PurposeGoals
Approach
User stories
Developer Checklist (Mandatory)
product-isissue to track any behavioral change or migration impact.Release note
Documentation
Training
Certification
Marketing
Automation tests
Security checks
Samples
Related PRs
Related Issues
wso2/product-is#25666
Migrations (if applicable)
Test environment
Learning
Summary by CodeRabbit
New Features
Documentation
Improvements
Tests
✏️ Tip: You can customize this high-level summary in your review settings.