Skip to content

Commit 1622d96

Browse files
authored
Merge pull request #1008 from NipuniBhagya/credential-mgt
Introduce end user credential management admin API
2 parents d84e927 + 1c0172f commit 1622d96

File tree

29 files changed

+2719
-0
lines changed

29 files changed

+2719
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
4+
~
5+
~ WSO2 LLC. licenses this file to you under the Apache License,
6+
~ Version 2.0 (the "License"); you may not use this file except
7+
~ in compliance with the License.
8+
~ You may obtain a copy of the License at
9+
~
10+
~ http://www.apache.org/licenses/LICENSE-2.0
11+
~
12+
~ Unless required by applicable law or agreed to in writing,
13+
~ software distributed under the License is distributed on an
14+
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
~ KIND, either express or implied. See the License for the
16+
~ specific language governing permissions and limitations
17+
~ under the License.
18+
-->
19+
20+
<project xmlns="http://maven.apache.org/POM/4.0.0"
21+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
23+
<modelVersion>4.0.0</modelVersion>
24+
25+
<parent>
26+
<groupId>org.wso2.carbon.identity.server.api</groupId>
27+
<artifactId>org.wso2.carbon.identity.api.server.credential.management</artifactId>
28+
<version>1.3.231-SNAPSHOT</version>
29+
<relativePath>../pom.xml</relativePath>
30+
</parent>
31+
32+
<artifactId>org.wso2.carbon.identity.api.server.credential.management.common</artifactId>
33+
<packaging>jar</packaging>
34+
35+
<dependencies>
36+
<dependency>
37+
<groupId>org.wso2.carbon.identity.framework</groupId>
38+
<artifactId>org.wso2.carbon.identity.core</artifactId>
39+
</dependency>
40+
<dependency>
41+
<groupId>org.wso2.carbon.identity.local.auth.fido</groupId>
42+
<artifactId>org.wso2.carbon.identity.application.authenticator.fido2</artifactId>
43+
</dependency>
44+
<dependency>
45+
<groupId>org.wso2.carbon.identity.notification.push</groupId>
46+
<artifactId>org.wso2.carbon.identity.notification.push.device.handler</artifactId>
47+
</dependency>
48+
<dependency>
49+
<groupId>org.wso2.carbon.identity.server.api</groupId>
50+
<artifactId>org.wso2.carbon.identity.api.server.common</artifactId>
51+
</dependency>
52+
</dependencies>
53+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
package org.wso2.carbon.identity.api.server.credential.management.common;
20+
21+
import org.wso2.carbon.identity.api.server.credential.management.common.dto.CredentialDTO;
22+
import org.wso2.carbon.identity.api.server.credential.management.common.dto.CredentialDeletionRequestDTO;
23+
import org.wso2.carbon.identity.api.server.credential.management.common.exception.CredentialMgtException;
24+
25+
import java.util.List;
26+
27+
/**
28+
* Credential Management Service interface.
29+
*/
30+
public interface CredentialHandler {
31+
/**
32+
* Retrieves credentials for a given entity.
33+
*/
34+
List<CredentialDTO> getCredentials(String entityId) throws CredentialMgtException;
35+
36+
/**
37+
* Deletes a credential for an entity.
38+
*/
39+
void deleteCredential(CredentialDeletionRequestDTO credentialDeletionRequest)
40+
throws CredentialMgtException;
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
* Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
package org.wso2.carbon.identity.api.server.credential.management.common;
20+
21+
import java.text.Collator;
22+
import java.util.Arrays;
23+
import java.util.Locale;
24+
25+
/**
26+
* Credential Management related constants.
27+
*/
28+
public class CredentialManagementConstants {
29+
30+
private CredentialManagementConstants() {
31+
32+
}
33+
34+
/**
35+
* Enum for supported credential types.
36+
*/
37+
public enum CredentialTypes {
38+
39+
PASSKEY("passkey"),
40+
PUSH_AUTH("push-auth");
41+
42+
private final String apiValue;
43+
44+
CredentialTypes(String apiValue) {
45+
46+
this.apiValue = apiValue;
47+
}
48+
49+
public String getApiValue() {
50+
51+
return apiValue;
52+
}
53+
54+
/**
55+
* Resolve the credential type for a given identifier. Accepts both API values and enum names.
56+
*
57+
* @param value Credential type provided by the caller.
58+
* @return Matching credential type if available.
59+
*/
60+
public static CredentialTypes fromString(String value) {
61+
62+
if (value == null) {
63+
64+
return null;
65+
}
66+
67+
String candidate = value.trim();
68+
if (candidate.isEmpty()) {
69+
70+
return null;
71+
}
72+
73+
Collator collator = Collator.getInstance(Locale.ROOT);
74+
collator.setStrength(Collator.PRIMARY);
75+
76+
return Arrays.stream(values())
77+
.filter(type -> collator.compare(type.name(), candidate) == 0
78+
|| collator.compare(type.getApiValue(), candidate) == 0)
79+
.findFirst()
80+
.orElse(null);
81+
}
82+
}
83+
84+
/**
85+
* Enum for error messages.
86+
*/
87+
public enum ErrorMessages {
88+
89+
// Server errors.
90+
ERROR_CODE_GET_PASSKEYS("65001", "Error retrieving registered passkeys.",
91+
"Unexpected server error while fetching registered passkeys for entity ID: %s."),
92+
ERROR_CODE_DELETE_PASSKEYS("65002", "Error deleting registered passkey.",
93+
"Unexpected server error while deleting registered passkey: %s for entity ID: %s."),
94+
ERROR_CODE_GET_PUSH_AUTH_DEVICE("65003", "Error retrieving registered push auth devices.",
95+
"Unexpected server error while fetching registered push auth device for entity ID: %s."),
96+
ERROR_CODE_DELETE_PUSH_AUTH_DEVICE("65004", "Error deleting registered push auth devices.",
97+
"Unexpected server error while deleting registered push auth device: %s for entity ID: %s."),
98+
99+
// Client errors.
100+
ERROR_CODE_DELETE_PASSKEY_CREDENTIAL("60001", "Error deleting credential.",
101+
"The request to delete the passkey credential: %s was invalid."),
102+
ERROR_CODE_DELETE_PUSH_AUTH_CREDENTIAL("60002", "Error deleting credential.",
103+
"The request to delete the push auth credential: %s was invalid."),
104+
ERROR_CODE_GET_USERNAME_FROM_USERID("60003", "Error retrieving username from user ID.",
105+
"The request to retrieve the username from the user ID: %s was invalid."),
106+
ERROR_CODE_ENTITY_NOT_FOUND("60004", "Entity not found",
107+
"Entity with ID %s not found in the tenant domain."),
108+
ERROR_CODE_INVALID_CREDENTIAL_TYPE("60005",
109+
"Invalid credential type.",
110+
"The provided credential type is not supported."),
111+
ERROR_CODE_INVALID_CREDENTIAL_ID("60006",
112+
"Invalid credential ID.",
113+
"The provided credential ID is invalid."),
114+
;
115+
116+
private static final String ERROR_PREFIX = "CM";
117+
public static final String ERROR_CODE_PUSH_AUTH_DEVICE_NOT_FOUND = "PDH-15010";
118+
private final String code;
119+
private final String message;
120+
private final String description;
121+
122+
ErrorMessages(String code, String message, String description) {
123+
124+
this.code = ERROR_PREFIX + "-" + code;
125+
this.message = message;
126+
this.description = description;
127+
}
128+
129+
public String getCode() {
130+
131+
return code;
132+
}
133+
134+
public String getMessage() {
135+
136+
return message;
137+
}
138+
139+
public String getDescription() {
140+
141+
return description;
142+
}
143+
144+
@Override
145+
public String toString() {
146+
147+
return code + ":" + message;
148+
}
149+
}
150+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
package org.wso2.carbon.identity.api.server.credential.management.common;
20+
21+
import org.wso2.carbon.identity.api.server.credential.management.common.dto.CredentialDTO;
22+
import org.wso2.carbon.identity.api.server.credential.management.common.dto.CredentialDeletionRequestDTO;
23+
24+
import java.util.List;
25+
26+
/**
27+
* Credential Management Service interface.
28+
*/
29+
public interface CredentialManagementService {
30+
31+
/**
32+
* Retrieves credentials for a given entity.
33+
*/
34+
List<CredentialDTO> getCredentials(String entityId);
35+
36+
/**
37+
* Deletes a credential of the specified type for an entity.
38+
*/
39+
void deleteCredential(CredentialDeletionRequestDTO credentialDeletionRequest);
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
package org.wso2.carbon.identity.api.server.credential.management.common;
20+
21+
import org.wso2.carbon.context.PrivilegedCarbonContext;
22+
import org.wso2.carbon.identity.application.authenticator.fido2.core.WebAuthnService;
23+
import org.wso2.carbon.identity.notification.push.device.handler.DeviceHandlerService;
24+
import org.wso2.carbon.user.core.service.RealmService;
25+
26+
/**
27+
* Service holder class for credential management related services.
28+
*/
29+
public class CredentialManagementServiceDataHolder {
30+
31+
private CredentialManagementServiceDataHolder() {
32+
33+
}
34+
35+
private static class WebAuthnServiceHolder {
36+
37+
private static final WebAuthnService SERVICE = new WebAuthnService();
38+
}
39+
40+
private static class PushDeviceHandlerHolder {
41+
42+
private static final DeviceHandlerService SERVICE = (DeviceHandlerService) PrivilegedCarbonContext
43+
.getThreadLocalCarbonContext().getOSGiService(DeviceHandlerService.class, null);
44+
}
45+
46+
private static class RealmServiceHolder {
47+
48+
private static final RealmService SERVICE = (RealmService) PrivilegedCarbonContext
49+
.getThreadLocalCarbonContext().getOSGiService(RealmService.class, null);
50+
}
51+
52+
/**
53+
* Get WebAuthnService OSGi service.
54+
*
55+
* @return WebAuthnService
56+
*/
57+
public static WebAuthnService getWebAuthnService() {
58+
59+
return WebAuthnServiceHolder.SERVICE;
60+
}
61+
62+
/**
63+
* Get Push DeviceHandler OSGi service.
64+
*
65+
* @return DeviceHandler
66+
*/
67+
public static DeviceHandlerService getPushDeviceHandler() {
68+
69+
return PushDeviceHandlerHolder.SERVICE;
70+
}
71+
72+
/**
73+
* Get RealmService OSGi service.
74+
*
75+
* @return RealmService
76+
*/
77+
public static RealmService getRealmService() {
78+
79+
return RealmServiceHolder.SERVICE;
80+
}
81+
}

0 commit comments

Comments
 (0)