Skip to content

Commit

Permalink
Merge pull request #2578 from ShanChathusanda93/dcr-impr-branch
Browse files Browse the repository at this point in the history
Allow OAuth2 application management through DCR in sub organizations
  • Loading branch information
ShanChathusanda93 authored Jan 7, 2025
2 parents 8a01652 + f1420ad commit 2302b85
Show file tree
Hide file tree
Showing 18 changed files with 420 additions and 60 deletions.
7 changes: 6 additions & 1 deletion components/org.wso2.carbon.identity.oauth.dcr/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@
<groupId>org.wso2.carbon.identity.framework</groupId>
<artifactId>org.wso2.carbon.identity.configuration.mgt.core</artifactId>
</dependency>

<dependency>
<groupId>org.wso2.carbon.identity.organization.management.core</groupId>
<artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -165,6 +168,8 @@
org.wso2.carbon.identity.application.common.model;version="${carbon.identity.framework.imp.pkg.version.range}",
org.wso2.carbon.identity.application.mgt.*;version="${carbon.identity.framework.imp.pkg.version.range}",
org.wso2.carbon.identity.application.authentication.framework.*;version="${carbon.identity.framework.imp.pkg.version.range}",
org.wso2.carbon.identity.organization.management.service; version="${carbon.identity.organization.management.core.version.range}",
org.wso2.carbon.identity.organization.management.service.exception; version="${carbon.identity.organization.management.core.version.range}",
javax.servlet.http; version="${imp.pkg.version.javax.servlet}",
org.wso2.carbon.user.api; version="${carbon.user.api.imp.pkg.version.range}",
org.wso2.carbon.identity.oauth.*;version="${identity.inbound.auth.oauth.imp.pkg.version.range}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public enum ErrorMessages {
SIGNATURE_VALIDATION_FAILED("Signature validation failed for the software statement"),
MANDATORY_SOFTWARE_STATEMENT("Mandatory software statement is missing"),
FAILED_TO_READ_SSA("Error occurred while reading the software statement"),
ADDITIONAL_ATTRIBUTE_ERROR("Error occurred while handling additional attributes");
ADDITIONAL_ATTRIBUTE_ERROR("Error occurred while handling additional attributes"),
FAILED_TO_RESOLVE_TENANT_DOMAIN("Error while resolving tenant domain from the organization id: %s");

private final String message;
private final String errorCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.wso2.carbon.identity.oauth.dcr.handler.RegistrationHandler;
import org.wso2.carbon.identity.oauth.dcr.handler.UnRegistrationHandler;
import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinder;
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -33,7 +34,6 @@
* This was deprecated as part of deprecating the legacy identity/register DCR endpoint.
* The recommendation is to use /identity/oauth2/dcr/v1.1 instead.
*/
@Deprecated
public class DCRDataHolder {

private static DCRDataHolder thisInstance = new DCRDataHolder();
Expand All @@ -42,6 +42,7 @@ public class DCRDataHolder {
private List<UnRegistrationHandler> unRegistrationHandlerList = new ArrayList<>();
private List<TokenBinder> tokenBinders = new ArrayList<>();
private ConfigurationManager configurationManager;
private OrganizationManager organizationManager;

private DCRDataHolder() {

Expand Down Expand Up @@ -111,4 +112,14 @@ public void setConfigurationManager(ConfigurationManager configurationManager) {

this.configurationManager = configurationManager;
}

public OrganizationManager getOrganizationManager() {

return organizationManager;
}

public void setOrganizationManager(OrganizationManager organizationManager) {

this.organizationManager = organizationManager;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.wso2.carbon.identity.oauth.dcr.processor.DCRProcessor;
import org.wso2.carbon.identity.oauth.dcr.service.DCRMService;
import org.wso2.carbon.identity.oauth2.token.bindings.TokenBinder;
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;

/**
* OAuth DCRM service component.
Expand All @@ -52,7 +53,6 @@
name = "identity.oauth.dcr",
immediate = true
)
@Deprecated
public class DCRServiceComponent {

private static final Log log = LogFactory.getLog(DCRServiceComponent.class);
Expand Down Expand Up @@ -254,4 +254,23 @@ protected void unregisterConfigurationManager(ConfigurationManager configuration
log.debug("Unregistering the ConfigurationManager in DCR Service Component.");
DCRDataHolder.getInstance().setConfigurationManager(null);
}

@Reference(
name = "organization.service",
service = OrganizationManager.class,
cardinality = ReferenceCardinality.MANDATORY,
policy = ReferencePolicy.DYNAMIC,
unbind = "unsetOrganizationManager"
)
protected void setOrganizationManager(OrganizationManager organizationManager) {

DCRDataHolder.getInstance().setOrganizationManager(organizationManager);
log.debug("Set the organization management service.");
}

protected void unsetOrganizationManager(OrganizationManager organizationManager) {

DCRDataHolder.getInstance().setOrganizationManager(null);
log.debug("Unset organization management service.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import org.wso2.carbon.identity.oauth2.OAuth2Constants;
import org.wso2.carbon.identity.oauth2.util.JWTSignatureValidationUtils;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
import org.wso2.carbon.user.api.UserStoreException;

import java.lang.reflect.InvocationTargetException;
Expand Down Expand Up @@ -105,12 +106,12 @@ public class DCRMService {
*/
public Application getApplication(String clientId) throws DCRMException {

validateRequestTenantDomain(clientId);
String tenantDomain = getTenantDomain();
validateRequestTenantDomain(clientId, tenantDomain);
OAuthConsumerAppDTO consumerAppDTO = getApplicationById(
clientId, DCRMUtils.isApplicationRolePermissionRequired());
clientId, DCRMUtils.isApplicationRolePermissionRequired(), tenantDomain);
// Get the jwksURI from the service provider.
String applicationName = consumerAppDTO.getApplicationName();
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
ServiceProvider serviceProvider = getServiceProvider(applicationName, tenantDomain);
String jwksURI = serviceProvider.getJwksUri();
if (StringUtils.isNotEmpty(jwksURI)) {
Expand Down Expand Up @@ -156,7 +157,7 @@ public Application getApplicationByName(String clientName) throws DCRMException
DCRMConstants.ErrorMessages.BAD_REQUEST_INSUFFICIENT_DATA, null);
}

String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String tenantDomain = getTenantDomain();
if (!isServiceProviderExist(clientName, tenantDomain)) {
throw DCRMUtils.generateClientException(
DCRMConstants.ErrorMessages.NOT_FOUND_APPLICATION_WITH_NAME, clientName);
Expand Down Expand Up @@ -203,10 +204,10 @@ public Application registerApplication(ApplicationRegistrationRequest registrati
*/
public void deleteApplication(String clientId) throws DCRMException {

validateRequestTenantDomain(clientId);
OAuthConsumerAppDTO appDTO = getApplicationById(clientId);
String tenantDomain = getTenantDomain();
validateRequestTenantDomain(clientId, tenantDomain);
OAuthConsumerAppDTO appDTO = getApplicationById(clientId, tenantDomain);
String applicationOwner = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String spName;
try {
spName = DCRDataHolder.getInstance().getApplicationManagementService()
Expand Down Expand Up @@ -241,9 +242,9 @@ public void deleteApplication(String clientId) throws DCRMException {
*/
public Application updateApplication(ApplicationUpdateRequest updateRequest, String clientId) throws DCRMException {

validateRequestTenantDomain(clientId);
OAuthConsumerAppDTO appDTO = getApplicationById(clientId);
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String tenantDomain = getTenantDomain();
validateRequestTenantDomain(clientId, tenantDomain);
OAuthConsumerAppDTO appDTO = getApplicationById(clientId, tenantDomain);
String applicationOwner = StringUtils.isNotBlank(updateRequest.getExtApplicationOwner()) ?
updateRequest.getExtApplicationOwner() :
PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
Expand Down Expand Up @@ -426,7 +427,7 @@ public Application updateApplication(ApplicationUpdateRequest updateRequest, Str
throw DCRMUtils.generateServerException(
DCRMConstants.ErrorMessages.FAILED_TO_UPDATE_APPLICATION, clientId, e);
}
OAuthConsumerAppDTO oAuthConsumerAppDTO = getApplicationById(clientId);
OAuthConsumerAppDTO oAuthConsumerAppDTO = getApplicationById(clientId, tenantDomain);
// Setting the jwksURI to be sent in the response.
oAuthConsumerAppDTO.setJwksURI(updateRequest.getJwksURI());
Application application = buildResponse(oAuthConsumerAppDTO, tenantDomain);
Expand Down Expand Up @@ -489,12 +490,13 @@ private String getDisplayNameProperty(ServiceProvider serviceProvider) {
return displayNameProperty.map(ServiceProviderProperty::getValue).orElse(null);
}

private OAuthConsumerAppDTO getApplicationById(String clientId) throws DCRMException {
private OAuthConsumerAppDTO getApplicationById(String clientId, String tenantDomain) throws DCRMException {

return getApplicationById(clientId, true);
return getApplicationById(clientId, true, tenantDomain);
}

private OAuthConsumerAppDTO getApplicationById(String clientId, boolean isApplicationRolePermissionRequired)
private OAuthConsumerAppDTO getApplicationById(String clientId, boolean isApplicationRolePermissionRequired,
String tenantDomain)
throws DCRMException {

if (StringUtils.isEmpty(clientId)) {
Expand All @@ -504,7 +506,7 @@ private OAuthConsumerAppDTO getApplicationById(String clientId, boolean isApplic
}

try {
OAuthConsumerAppDTO dto = oAuthAdminService.getOAuthApplicationData(clientId);
OAuthConsumerAppDTO dto = oAuthAdminService.getOAuthApplicationData(clientId, tenantDomain);
if (dto == null || StringUtils.isEmpty(dto.getApplicationName())) {
throw DCRMUtils.generateClientException(
DCRMConstants.ErrorMessages.NOT_FOUND_APPLICATION_WITH_ID, clientId);
Expand All @@ -529,8 +531,7 @@ private Application createOAuthApplication(ApplicationRegistrationRequest regist
String applicationOwner = StringUtils.isNotBlank(registrationRequest.getExtApplicationOwner()) ?
registrationRequest.getExtApplicationOwner() :
PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();

String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String tenantDomain = getTenantDomain();

/*
* ApplicationOwner will be null and a server error is thrown when creating an app, if the api authentication/
Expand Down Expand Up @@ -566,7 +567,7 @@ private Application createOAuthApplication(ApplicationRegistrationRequest regist
}

if (StringUtils.isNotEmpty(registrationRequest.getConsumerKey()) && isClientIdExist(
registrationRequest.getConsumerKey())) {
registrationRequest.getConsumerKey(), tenantDomain)) {
throw DCRMUtils.generateClientException(DCRMConstants.ErrorMessages.CONFLICT_EXISTING_CLIENT_ID,
registrationRequest.getConsumerKey());
}
Expand Down Expand Up @@ -941,10 +942,10 @@ private boolean isServiceProviderExist(String serviceProviderName, String tenant
* @return true if application exists with the client id.
* @throws DCRMException in case of failure.
*/
private boolean isClientIdExist(String clientId) throws DCRMException {
private boolean isClientIdExist(String clientId, String tenantDomain) throws DCRMException {

try {
OAuthConsumerAppDTO dto = oAuthAdminService.getOAuthApplicationData(clientId);
OAuthConsumerAppDTO dto = oAuthAdminService.getOAuthApplicationData(clientId, tenantDomain);
return dto != null && StringUtils.isNotBlank(dto.getApplicationName());
} catch (IdentityOAuthAdminException e) {
if (e.getCause() instanceof InvalidOAuthClientException) {
Expand Down Expand Up @@ -1144,7 +1145,7 @@ private String escapeQueryParamsIfPresent(String redirectURI) {
private boolean isUserAuthorized(String clientId) throws DCRMServerException {

try {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String tenantDomain = getTenantDomain();
String spName = DCRDataHolder.getInstance().getApplicationManagementService()
.getServiceProviderNameByClientId(clientId, DCRMConstants.OAUTH2, tenantDomain);
String threadLocalUserName = CarbonContext.getThreadLocalCarbonContext().getUsername();
Expand Down Expand Up @@ -1176,10 +1177,10 @@ private static boolean clientIdMatchesRegex(String clientId, String clientIdVali
* @param clientId Consumer key of application.
* @throws DCRMException DCRMException
*/
private void validateRequestTenantDomain(String clientId) throws DCRMException {
private void validateRequestTenantDomain(String clientId, String tenantDomain) throws DCRMException {

try {
String tenantDomainOfApp = OAuth2Util.getTenantDomainOfOauthApp(clientId);
String tenantDomainOfApp = OAuth2Util.getTenantDomainOfOauthApp(clientId, tenantDomain);
OAuth2Util.validateRequestTenantDomain(tenantDomainOfApp);
} catch (InvalidOAuthClientException e) {
throw new DCRMClientException(DCRMConstants.ErrorMessages.TENANT_DOMAIN_MISMATCH.getErrorCode(),
Expand Down Expand Up @@ -1275,4 +1276,21 @@ private void addSPProperties(Map<String, Object> spProperties, ServiceProvider s
}
serviceProvider.setSpProperties(serviceProviderProperties);
}

private static String getTenantDomain() throws DCRMServerException {

String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String applicationResidentOrgId = PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getApplicationResidentOrganizationId();
if (StringUtils.isNotEmpty(applicationResidentOrgId)) {
try {
tenantDomain = DCRDataHolder.getInstance().getOrganizationManager()
.resolveTenantDomain(applicationResidentOrgId);
} catch (OrganizationManagementException e) {
throw DCRMUtils.generateServerException(
DCRMConstants.ErrorMessages.FAILED_TO_RESOLVE_TENANT_DOMAIN, applicationResidentOrgId, e);
}
}
return tenantDomain;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
* This was deprecated as part of deprecating the legacy identity/register DCR endpoint.
* The recommendation is to use /identity/oauth2/dcr/v1.1 instead.
*/
@Deprecated
public class DCRMUtils {

private static final Log log = LogFactory.getLog(DCRMUtils.class);
Expand Down
Loading

0 comments on commit 2302b85

Please sign in to comment.