-
Notifications
You must be signed in to change notification settings - Fork 173
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
Changes from all commits
f2e6dea
a6fbfcb
40fe324
8b07432
0647005
758a299
bf0426b
bef86d0
d29080e
0700b39
270a78f
9fb1f58
d5957e5
ad8d73a
d964124
04b72a2
e7fe9da
6464f98
8427e0d
c8b68f4
55c3c53
7ec8883
b267572
b705fa8
1c0172f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <!-- | ||
| ~ Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). | ||
| ~ | ||
| ~ WSO2 LLC. licenses this file to you under the Apache License, | ||
| ~ Version 2.0 (the "License"); you may not use this file except | ||
| ~ in compliance with the License. | ||
| ~ You may obtain a copy of the License at | ||
| ~ | ||
| ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
| ~ | ||
| ~ Unless required by applicable law or agreed to in writing, | ||
| ~ software distributed under the License is distributed on an | ||
| ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| ~ KIND, either express or implied. See the License for the | ||
| ~ specific language governing permissions and limitations | ||
| ~ under the License. | ||
| --> | ||
|
|
||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
|
|
||
| <parent> | ||
| <groupId>org.wso2.carbon.identity.server.api</groupId> | ||
| <artifactId>org.wso2.carbon.identity.api.server.credential.management</artifactId> | ||
| <version>1.3.231-SNAPSHOT</version> | ||
| <relativePath>../pom.xml</relativePath> | ||
| </parent> | ||
|
|
||
| <artifactId>org.wso2.carbon.identity.api.server.credential.management.common</artifactId> | ||
| <packaging>jar</packaging> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>org.wso2.carbon.identity.framework</groupId> | ||
| <artifactId>org.wso2.carbon.identity.core</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.wso2.carbon.identity.local.auth.fido</groupId> | ||
| <artifactId>org.wso2.carbon.identity.application.authenticator.fido2</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.wso2.carbon.identity.notification.push</groupId> | ||
| <artifactId>org.wso2.carbon.identity.notification.push.device.handler</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.wso2.carbon.identity.server.api</groupId> | ||
| <artifactId>org.wso2.carbon.identity.api.server.common</artifactId> | ||
| </dependency> | ||
| </dependencies> | ||
| </project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| /* | ||
| * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). | ||
| * | ||
| * WSO2 LLC. licenses this file to you under the Apache License, | ||
| * Version 2.0 (the "License"); you may not use this file except | ||
| * in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
|
|
||
| package org.wso2.carbon.identity.api.server.credential.management.common; | ||
|
|
||
| import org.wso2.carbon.identity.api.server.credential.management.common.dto.CredentialDTO; | ||
| import org.wso2.carbon.identity.api.server.credential.management.common.dto.CredentialDeletionRequestDTO; | ||
| import org.wso2.carbon.identity.api.server.credential.management.common.exception.CredentialMgtException; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Credential Management Service interface. | ||
| */ | ||
| public interface CredentialHandler { | ||
| /** | ||
| * Retrieves credentials for a given entity. | ||
| */ | ||
| List<CredentialDTO> getCredentials(String entityId) throws CredentialMgtException; | ||
|
|
||
| /** | ||
| * Deletes a credential for an entity. | ||
| */ | ||
| void deleteCredential(CredentialDeletionRequestDTO credentialDeletionRequest) | ||
| throws CredentialMgtException; | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,150 @@ | ||||||||||||||||||
| /* | ||||||||||||||||||
| * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). | ||||||||||||||||||
| * | ||||||||||||||||||
| * WSO2 LLC. licenses this file to you under the Apache License, | ||||||||||||||||||
| * Version 2.0 (the "License"); you may not use this file except | ||||||||||||||||||
| * in compliance with the License. | ||||||||||||||||||
| * You may obtain a copy of the License at | ||||||||||||||||||
| * | ||||||||||||||||||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||||||||||||||||||
| * | ||||||||||||||||||
| * Unless required by applicable law or agreed to in writing, | ||||||||||||||||||
| * software distributed under the License is distributed on an | ||||||||||||||||||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||||||||||||||||||
| * KIND, either express or implied. See the License for the | ||||||||||||||||||
| * specific language governing permissions and limitations | ||||||||||||||||||
| * under the License. | ||||||||||||||||||
| */ | ||||||||||||||||||
|
|
||||||||||||||||||
| package org.wso2.carbon.identity.api.server.credential.management.common; | ||||||||||||||||||
|
|
||||||||||||||||||
| import java.text.Collator; | ||||||||||||||||||
| import java.util.Arrays; | ||||||||||||||||||
| import java.util.Locale; | ||||||||||||||||||
|
|
||||||||||||||||||
| /** | ||||||||||||||||||
| * Credential Management related constants. | ||||||||||||||||||
| */ | ||||||||||||||||||
| public class CredentialManagementConstants { | ||||||||||||||||||
|
|
||||||||||||||||||
| private CredentialManagementConstants() { | ||||||||||||||||||
|
|
||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| /** | ||||||||||||||||||
| * Enum for supported credential types. | ||||||||||||||||||
| */ | ||||||||||||||||||
| public enum CredentialTypes { | ||||||||||||||||||
|
|
||||||||||||||||||
| PASSKEY("passkey"), | ||||||||||||||||||
| PUSH_AUTH("push-auth"); | ||||||||||||||||||
|
|
||||||||||||||||||
| private final String apiValue; | ||||||||||||||||||
|
|
||||||||||||||||||
| CredentialTypes(String apiValue) { | ||||||||||||||||||
|
|
||||||||||||||||||
| this.apiValue = apiValue; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| public String getApiValue() { | ||||||||||||||||||
|
|
||||||||||||||||||
| return apiValue; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| /** | ||||||||||||||||||
| * Resolve the credential type for a given identifier. Accepts both API values and enum names. | ||||||||||||||||||
| * | ||||||||||||||||||
| * @param value Credential type provided by the caller. | ||||||||||||||||||
| * @return Matching credential type if available. | ||||||||||||||||||
| */ | ||||||||||||||||||
| public static CredentialTypes fromString(String value) { | ||||||||||||||||||
|
|
||||||||||||||||||
| if (value == null) { | ||||||||||||||||||
|
|
||||||||||||||||||
| return null; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| String candidate = value.trim(); | ||||||||||||||||||
| if (candidate.isEmpty()) { | ||||||||||||||||||
|
|
||||||||||||||||||
| return null; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| 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() | ||||||||||||||||||
| .orElse(null); | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| /** | ||||||||||||||||||
| * Enum for error messages. | ||||||||||||||||||
| */ | ||||||||||||||||||
| public enum ErrorMessages { | ||||||||||||||||||
|
|
||||||||||||||||||
| // Server errors. | ||||||||||||||||||
| ERROR_CODE_GET_PASSKEYS("65001", "Error retrieving registered passkeys.", | ||||||||||||||||||
| "Unexpected server error while fetching registered passkeys for entity ID: %s."), | ||||||||||||||||||
| ERROR_CODE_DELETE_PASSKEYS("65002", "Error deleting registered passkey.", | ||||||||||||||||||
| "Unexpected server error while deleting registered passkey: %s for entity ID: %s."), | ||||||||||||||||||
| ERROR_CODE_GET_PUSH_AUTH_DEVICE("65003", "Error retrieving registered push auth devices.", | ||||||||||||||||||
| "Unexpected server error while fetching registered push auth device for entity ID: %s."), | ||||||||||||||||||
| ERROR_CODE_DELETE_PUSH_AUTH_DEVICE("65004", "Error deleting registered push auth devices.", | ||||||||||||||||||
| "Unexpected server error while deleting registered push auth device: %s for entity ID: %s."), | ||||||||||||||||||
|
|
||||||||||||||||||
| // Client errors. | ||||||||||||||||||
| ERROR_CODE_DELETE_PASSKEY_CREDENTIAL("60001", "Error deleting credential.", | ||||||||||||||||||
| "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."), | ||||||||||||||||||
|
Comment on lines
+100
to
+103
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix typos: double spaces in error descriptions. Lines 101 and 103 contain double spaces before "was invalid". ✏️ Proposed fix 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."),📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| ERROR_CODE_GET_USERNAME_FROM_USERID("60003", "Error retrieving username from user ID.", | ||||||||||||||||||
| "The request to retrieve the username from the user ID: %s was invalid."), | ||||||||||||||||||
| ERROR_CODE_ENTITY_NOT_FOUND("60004", "Entity not found", | ||||||||||||||||||
| "Entity with ID %s not found in the tenant domain."), | ||||||||||||||||||
| ERROR_CODE_INVALID_CREDENTIAL_TYPE("60005", | ||||||||||||||||||
| "Invalid credential type.", | ||||||||||||||||||
| "The provided credential type is not supported."), | ||||||||||||||||||
| ERROR_CODE_INVALID_CREDENTIAL_ID("60006", | ||||||||||||||||||
| "Invalid credential ID.", | ||||||||||||||||||
| "The provided credential ID is invalid."), | ||||||||||||||||||
| ; | ||||||||||||||||||
|
|
||||||||||||||||||
| private static final String ERROR_PREFIX = "CM"; | ||||||||||||||||||
| public static final String ERROR_CODE_PUSH_AUTH_DEVICE_NOT_FOUND = "PDH-15010"; | ||||||||||||||||||
| private final String code; | ||||||||||||||||||
| private final String message; | ||||||||||||||||||
| private final String description; | ||||||||||||||||||
|
|
||||||||||||||||||
| ErrorMessages(String code, String message, String description) { | ||||||||||||||||||
|
|
||||||||||||||||||
| this.code = ERROR_PREFIX + "-" + code; | ||||||||||||||||||
| this.message = message; | ||||||||||||||||||
| this.description = description; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| public String getCode() { | ||||||||||||||||||
|
|
||||||||||||||||||
| return code; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| public String getMessage() { | ||||||||||||||||||
|
|
||||||||||||||||||
| return message; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| public String getDescription() { | ||||||||||||||||||
|
|
||||||||||||||||||
| return description; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| @Override | ||||||||||||||||||
| public String toString() { | ||||||||||||||||||
|
|
||||||||||||||||||
| return code + ":" + message; | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| /* | ||
| * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). | ||
| * | ||
| * WSO2 LLC. licenses this file to you under the Apache License, | ||
| * Version 2.0 (the "License"); you may not use this file except | ||
| * in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
|
|
||
| package org.wso2.carbon.identity.api.server.credential.management.common; | ||
|
|
||
| import org.wso2.carbon.identity.api.server.credential.management.common.dto.CredentialDTO; | ||
| import org.wso2.carbon.identity.api.server.credential.management.common.dto.CredentialDeletionRequestDTO; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Credential Management Service interface. | ||
| */ | ||
| public interface CredentialManagementService { | ||
|
|
||
| /** | ||
| * Retrieves credentials for a given entity. | ||
| */ | ||
| List<CredentialDTO> getCredentials(String entityId); | ||
|
|
||
| /** | ||
| * Deletes a credential of the specified type for an entity. | ||
| */ | ||
| void deleteCredential(CredentialDeletionRequestDTO credentialDeletionRequest); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| /* | ||
| * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). | ||
| * | ||
| * WSO2 LLC. licenses this file to you under the Apache License, | ||
| * Version 2.0 (the "License"); you may not use this file except | ||
| * in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
|
|
||
| package org.wso2.carbon.identity.api.server.credential.management.common; | ||
|
|
||
| import org.wso2.carbon.context.PrivilegedCarbonContext; | ||
| import org.wso2.carbon.identity.application.authenticator.fido2.core.WebAuthnService; | ||
| import org.wso2.carbon.identity.notification.push.device.handler.DeviceHandlerService; | ||
| import org.wso2.carbon.user.core.service.RealmService; | ||
|
|
||
| /** | ||
| * Service holder class for credential management related services. | ||
| */ | ||
| public class CredentialManagementServiceDataHolder { | ||
|
|
||
| private CredentialManagementServiceDataHolder() { | ||
|
|
||
| } | ||
|
|
||
| private static class WebAuthnServiceHolder { | ||
|
|
||
| private static final WebAuthnService SERVICE = new WebAuthnService(); | ||
| } | ||
|
Comment on lines
+35
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Direct instantiation of OSGi service will fail. Line 37 directly instantiates Apply this diff to retrieve the service from OSGi: private static class WebAuthnServiceHolder {
- private static final WebAuthnService SERVICE = new WebAuthnService();
+ private static final WebAuthnService SERVICE = (WebAuthnService) PrivilegedCarbonContext
+ .getThreadLocalCarbonContext().getOSGiService(WebAuthnService.class, null);
}🤖 Prompt for AI Agents |
||
|
|
||
| private static class PushDeviceHandlerHolder { | ||
|
|
||
| private static final DeviceHandlerService SERVICE = (DeviceHandlerService) PrivilegedCarbonContext | ||
| .getThreadLocalCarbonContext().getOSGiService(DeviceHandlerService.class, null); | ||
| } | ||
|
|
||
| private static class RealmServiceHolder { | ||
|
|
||
| private static final RealmService SERVICE = (RealmService) PrivilegedCarbonContext | ||
| .getThreadLocalCarbonContext().getOSGiService(RealmService.class, null); | ||
| } | ||
|
|
||
| /** | ||
| * Get WebAuthnService OSGi service. | ||
| * | ||
| * @return WebAuthnService | ||
| */ | ||
| public static WebAuthnService getWebAuthnService() { | ||
|
|
||
| return WebAuthnServiceHolder.SERVICE; | ||
| } | ||
|
|
||
| /** | ||
| * Get Push DeviceHandler OSGi service. | ||
| * | ||
| * @return DeviceHandler | ||
| */ | ||
| public static DeviceHandlerService getPushDeviceHandler() { | ||
|
|
||
| return PushDeviceHandlerHolder.SERVICE; | ||
| } | ||
|
|
||
| /** | ||
| * Get RealmService OSGi service. | ||
| * | ||
| * @return RealmService | ||
| */ | ||
| public static RealmService getRealmService() { | ||
|
|
||
| return RealmServiceHolder.SERVICE; | ||
| } | ||
| } | ||
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:
📝 Committable suggestion
🤖 Prompt for AI Agents