Skip to content
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

Allow OAuth2 application management through DCR in sub organizations #2578

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
ShanChathusanda93 marked this conversation as resolved.
Show resolved Hide resolved
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
Loading