diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java
index 5f05dfb337..1f043c7b86 100644
--- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java
@@ -23,6 +23,7 @@ import org.wso2.carbon.apimgt.application.extension.api.util.APIUtil;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.user.api.UserRealm;
import org.wso2.carbon.user.api.UserStoreException;
+import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
@@ -120,7 +121,8 @@ public class ApiPermissionFilter implements Filter {
try {
UserRealm userRealm = APIUtil.getRealmService().getTenantUserRealm(PrivilegedCarbonContext
.getThreadLocalCarbonContext().getTenantId());
- return userRealm.getAuthorizationManager().isUserAuthorized(username, permission, action);
+ String tenantAwareUsername = MultitenantUtils.getTenantAwareUsername(username);
+ return userRealm.getAuthorizationManager().isUserAuthorized(tenantAwareUsername, permission, action);
} catch (UserStoreException e) {
String errorMsg = String.format("Unable to authorize the user : %s", username);
log.error(errorMsg, e);
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml
index 591725fa12..9c41774ce5 100644
--- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml
@@ -37,14 +37,14 @@
Register application
- /device-mgt/api/application
+ /manage/api/subscribe
/register
POST
application_user
Delete application
- /device-mgt/api/application
+ /manage/api/subscribe
/unregister
DELETE
application_user
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java
index 8886d756bf..7930aab2b3 100644
--- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java
@@ -389,13 +389,13 @@ public class DeviceManagementServiceComponent {
}
- protected void setDeviceTaskManagerService(DeviceTaskManagerService emailSenderService) {
+ protected void setDeviceTaskManagerService(DeviceTaskManagerService deviceTaskManagerService) {
if (log.isDebugEnabled()) {
}
- DeviceManagementDataHolder.getInstance().setDeviceTaskManagerService(emailSenderService);
+ DeviceManagementDataHolder.getInstance().setDeviceTaskManagerService(deviceTaskManagerService);
}
- protected void unsetDeviceTaskManagerService(DeviceTaskManagerService emailSenderService) {
+ protected void unsetDeviceTaskManagerService(DeviceTaskManagerService deviceTaskManagerService) {
if (log.isDebugEnabled()) {
}
DeviceManagementDataHolder.getInstance().setDeviceTaskManagerService(null);
diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/ScopeValidationHandler.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/ScopeValidationHandler.java
new file mode 100644
index 0000000000..0c3964e9c0
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/ScopeValidationHandler.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.device.mgt.oauth.extensions.handlers;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.device.mgt.oauth.extensions.internal.OAuthExtensionsDataHolder;
+import org.wso2.carbon.identity.oauth.cache.CacheEntry;
+import org.wso2.carbon.identity.oauth.cache.OAuthCache;
+import org.wso2.carbon.identity.oauth.cache.OAuthCacheKey;
+import org.wso2.carbon.identity.oauth.config.OAuthServerConfiguration;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO;
+import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.model.ResourceScopeCacheEntry;
+import org.wso2.carbon.identity.oauth2.validators.OAuth2ScopeValidator;
+
+import java.util.Map;
+
+public class ScopeValidationHandler extends OAuth2ScopeValidator {
+
+ private final static Log log = LogFactory.getLog(ScopeValidationHandler.class);
+ private Map scopeValidators;
+
+ private final String DEFAULT_PREFIX = "default";
+
+ public ScopeValidationHandler() {
+ scopeValidators = OAuthExtensionsDataHolder.getInstance().getScopeValidators();
+ }
+
+ public boolean validateScope(AccessTokenDO accessTokenDO, String resource) throws IdentityOAuth2Exception {
+
+ //returns true if scope validators are not defined
+ if (scopeValidators == null || scopeValidators.isEmpty()) {
+ if(log.isDebugEnabled()){
+ log.debug("OAuth2 scope validators are not loaded");
+ }
+ return true;
+ }
+
+ String resourceScope = getResourceScope(resource);
+
+ //returns true if scope does not exist for the resource
+ if (resourceScope == null) {
+ if(log.isDebugEnabled()){
+ log.debug("Resource '" + resource + "' is not protected with a scope");
+ }
+ return true;
+ }
+
+ String scope[] = resourceScope.split(":");
+ String scopePrefix = scope[0];
+
+ OAuth2ScopeValidator scopeValidator = scopeValidators.get(scopePrefix);
+
+ if (scopeValidator == null) {
+ if(log.isDebugEnabled()){
+ log.debug("OAuth2 scope validator cannot be identified for '" + scopePrefix + "' scope prefix");
+ }
+
+ // loading default scope validator if matching validator is not found
+ scopeValidator = scopeValidators.get(DEFAULT_PREFIX);
+ if(log.isDebugEnabled()){
+ log.debug("Loading default scope validator");
+ }
+
+ if (scopeValidator == null) {
+ if(log.isDebugEnabled()){
+ log.debug("Default scope validator is not available");
+ }
+ return true;
+ }
+ }
+
+ // validate scope via relevant scope validator that matches with the prefix
+ return scopeValidator.validateScope(accessTokenDO, resourceScope);
+ }
+
+ private String getResourceScope(String resource) {
+
+ String resourceScope = null;
+ boolean cacheHit = false;
+ // Check the cache, if caching is enabled.
+ if (OAuthServerConfiguration.getInstance().isCacheEnabled()) {
+ OAuthCache oauthCache = OAuthCache.getInstance();
+ OAuthCacheKey cacheKey = new OAuthCacheKey(resource);
+ CacheEntry result = oauthCache.getValueFromCache(cacheKey);
+
+ //Cache hit
+ if (result instanceof ResourceScopeCacheEntry) {
+ resourceScope = ((ResourceScopeCacheEntry) result).getScope();
+ cacheHit = true;
+ }
+ }
+
+ TokenMgtDAO tokenMgtDAO = new TokenMgtDAO();
+ if (!cacheHit) {
+ try {
+ resourceScope = tokenMgtDAO.findScopeOfResource(resource);
+ } catch (IdentityOAuth2Exception e) {
+ log.error("Error occurred while retrieving scope for resource '" + resource + "'");
+ }
+
+ if (OAuthServerConfiguration.getInstance().isCacheEnabled()) {
+ OAuthCache oauthCache = OAuthCache.getInstance();
+ OAuthCacheKey cacheKey = new OAuthCacheKey(resource);
+ ResourceScopeCacheEntry cacheEntry = new ResourceScopeCacheEntry(resourceScope);
+ //Store resourceScope in cache even if it is null (to avoid database calls when accessing resources for
+ //which scopes haven't been defined).
+ oauthCache.addToCache(cacheKey, cacheEntry);
+ }
+ }
+ return resourceScope;
+ }
+
+}
diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionServiceComponent.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionServiceComponent.java
index 06ee47fcf6..881df6fd86 100644
--- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionServiceComponent.java
+++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionServiceComponent.java
@@ -21,7 +21,11 @@ package org.wso2.carbon.device.mgt.oauth.extensions.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
+
+import org.wso2.carbon.device.mgt.oauth.extensions.validators.ExtendedJDBCScopeValidator;
import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService;
+import org.wso2.carbon.identity.oauth2.validators.JDBCScopeValidator;
+import org.wso2.carbon.identity.oauth2.validators.OAuth2ScopeValidator;
import org.wso2.carbon.user.core.service.RealmService;
/**
@@ -38,6 +42,12 @@ import org.wso2.carbon.user.core.service.RealmService;
* policy="dynamic"
* bind="setOAuth2ValidationService"
* unbind="unsetOAuth2ValidationService"
+ * * @scr.reference name="scope.validator.service"
+ * interface="org.wso2.carbon.identity.oauth2.validators.OAuth2ScopeValidator"
+ * cardinality="0..n"
+ * policy="dynamic"
+ * bind="addScopeValidator"
+ * unbind="removeScopeValidator"
*/
public class OAuthExtensionServiceComponent {
@@ -45,6 +55,8 @@ public class OAuthExtensionServiceComponent {
private static final String REPOSITORY = "repository";
private static final String CONFIGURATION = "conf";
private static final String APIM_CONF_FILE = "api-manager.xml";
+ private static final String PERMISSION_SCOPE_PREFIX = "perm";
+ private static final String DEFAULT_PREFIX = "default";
@SuppressWarnings("unused")
@@ -52,6 +64,14 @@ public class OAuthExtensionServiceComponent {
if (log.isDebugEnabled()) {
log.debug("Starting OAuthExtensionBundle");
}
+
+ ExtendedJDBCScopeValidator permissionBasedScopeValidator = new ExtendedJDBCScopeValidator();
+ JDBCScopeValidator roleBasedScopeValidator = new JDBCScopeValidator();
+ OAuthExtensionsDataHolder.getInstance().addScopeValidator(permissionBasedScopeValidator,
+ PERMISSION_SCOPE_PREFIX);
+ OAuthExtensionsDataHolder.getInstance().addScopeValidator(roleBasedScopeValidator,
+ DEFAULT_PREFIX);
+
}
@SuppressWarnings("unused")
@@ -109,5 +129,21 @@ public class OAuthExtensionServiceComponent {
OAuthExtensionsDataHolder.getInstance().setoAuth2TokenValidationService(null);
}
+ /**
+ * Add scope validator to the map.
+ * @param scopesValidator
+ */
+ protected void addScopeValidator(OAuth2ScopeValidator scopesValidator) {
+ OAuthExtensionsDataHolder.getInstance().addScopeValidator(scopesValidator, DEFAULT_PREFIX);
+ }
+
+ /**
+ * unset scope validator.
+ * @param scopesValidator
+ */
+ protected void removeScopeValidator(OAuth2ScopeValidator scopesValidator) {
+ OAuthExtensionsDataHolder.getInstance().removeScopeValidator();
+ }
+
}
diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionsDataHolder.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionsDataHolder.java
index 4f401b3db5..2c4f25705d 100644
--- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionsDataHolder.java
+++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionsDataHolder.java
@@ -19,9 +19,12 @@
package org.wso2.carbon.device.mgt.oauth.extensions.internal;
import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService;
+import org.wso2.carbon.identity.oauth2.validators.OAuth2ScopeValidator;
import org.wso2.carbon.user.core.service.RealmService;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* This holds the OSGi service references required for oauth extensions bundle.
@@ -31,10 +34,13 @@ public class OAuthExtensionsDataHolder {
private RealmService realmService;
private OAuth2TokenValidationService oAuth2TokenValidationService;
private List whitelistedScopes;
+ private Map scopeValidators;
private static OAuthExtensionsDataHolder thisInstance = new OAuthExtensionsDataHolder();
- private OAuthExtensionsDataHolder() {}
+ private OAuthExtensionsDataHolder() {
+ scopeValidators = new HashMap<>();
+ }
public static OAuthExtensionsDataHolder getInstance() {
return thisInstance;
@@ -71,4 +77,20 @@ public class OAuthExtensionsDataHolder {
this.whitelistedScopes = whitelistedScopes;
}
+ public Map getScopeValidators() {
+ return scopeValidators;
+ }
+
+ public void setScopeValidators(Map scopeValidators) {
+ this.scopeValidators = scopeValidators;
+ }
+
+ public void addScopeValidator(OAuth2ScopeValidator oAuth2ScopeValidator, String prefix) {
+ scopeValidators.put(prefix, oAuth2ScopeValidator);
+ }
+
+ public void removeScopeValidator() {
+ scopeValidators = null;
+ }
+
}
diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedJDBCScopeValidator.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedJDBCScopeValidator.java
index 8f5ffa2514..58c975bbec 100644
--- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedJDBCScopeValidator.java
+++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedJDBCScopeValidator.java
@@ -45,7 +45,7 @@ import java.util.List;
import java.util.Set;
@SuppressWarnings("unused")
-public class ExtendedJDBCScopeValidator extends OAuth2ScopeValidator{
+public class ExtendedJDBCScopeValidator extends OAuth2ScopeValidator {
private static final Log log = LogFactory.getLog(ExtendedJDBCScopeValidator.class);
private static final String UI_EXECUTE = "ui.execute";
diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/PermissionBasedScopeValidator.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/PermissionBasedScopeValidator.java
new file mode 100644
index 0000000000..5be19a5a0c
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/PermissionBasedScopeValidator.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.device.mgt.oauth.extensions.validators;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.base.MultitenantConstants;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.device.mgt.oauth.extensions.internal.OAuthExtensionsDataHolder;
+import org.wso2.carbon.identity.application.common.model.User;
+import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO;
+import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.validators.OAuth2ScopeValidator;
+import org.wso2.carbon.user.api.AuthorizationManager;
+import org.wso2.carbon.user.api.UserStoreException;
+import org.wso2.carbon.user.core.service.RealmService;
+import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+@SuppressWarnings("unused")
+public class PermissionBasedScopeValidator extends OAuth2ScopeValidator {
+
+ private static final Log log = LogFactory.getLog(PermissionBasedScopeValidator.class);
+ private static final String UI_EXECUTE = "ui.execute";
+
+
+ @Override
+ public boolean validateScope(AccessTokenDO accessTokenDO, String resourceScope) throws IdentityOAuth2Exception {
+ //Get the list of scopes associated with the access token
+ String[] scopes = accessTokenDO.getScope();
+
+ //If no scopes are associated with the token
+ if (scopes == null || scopes.length == 0) {
+ return true;
+ }
+
+ TokenMgtDAO tokenMgtDAO = new TokenMgtDAO();
+
+ List scopeList = new ArrayList<>(Arrays.asList(scopes));
+
+ //If the access token does not bear the scope required for accessing the Resource.
+ if(!scopeList.contains(resourceScope)){
+ if(log.isDebugEnabled()){
+ log.debug("Access token '" + accessTokenDO.getAccessToken() + "' does not bear the scope '" +
+ resourceScope + "'");
+ }
+ return false;
+ }
+
+ try {
+ //Get the permissions associated with the scope, if any
+ Set permissionsOfScope = tokenMgtDAO.getRolesOfScopeByScopeKey(resourceScope);
+
+ //If the scope doesn't have any permissions associated with it.
+ if(permissionsOfScope == null || permissionsOfScope.isEmpty()){
+ if(log.isDebugEnabled()){
+ log.debug("Did not find any roles associated to the scope " + resourceScope);
+ }
+ return true;
+ }
+
+ if(log.isDebugEnabled()){
+ StringBuilder logMessage = new StringBuilder("Found permissions of scope '" + resourceScope + "' ");
+ for(String permission : permissionsOfScope){
+ logMessage.append(permission);
+ logMessage.append(", ");
+ }
+ log.debug(logMessage.toString());
+ }
+
+ User authorizedUser = accessTokenDO.getAuthzUser();
+ RealmService realmService = OAuthExtensionsDataHolder.getInstance().getRealmService();
+
+ int tenantId = realmService.getTenantManager().getTenantId(authorizedUser.getTenantDomain());
+
+ if (tenantId == 0 || tenantId == -1) {
+ tenantId = IdentityTenantUtil.getTenantIdOfUser(authorizedUser.getUserName());
+ }
+
+ AuthorizationManager authorizationManager;
+ String[] userRoles;
+ boolean tenantFlowStarted = false;
+
+ try{
+ //If this is a tenant user
+ if(tenantId != MultitenantConstants.SUPER_TENANT_ID){
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
+ realmService.getTenantManager().getDomain(tenantId),true);
+ tenantFlowStarted = true;
+ }
+
+ authorizationManager = realmService.getTenantUserRealm(tenantId).getAuthorizationManager();
+
+ } finally {
+ if (tenantFlowStarted) {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+ boolean status = false;
+ String username = MultitenantUtils.getTenantAwareUsername(authorizedUser.getUserName());
+ for (String permission : permissionsOfScope) {
+ if (authorizationManager != null) {
+ String userStore = authorizedUser.getUserStoreDomain();
+
+ if (userStore != null) {
+ status = authorizationManager
+ .isUserAuthorized(userStore + "/" + username, permission, UI_EXECUTE);
+ } else {
+ status = authorizationManager.isUserAuthorized(username , permission, UI_EXECUTE);
+ }
+ if (status) {
+ break;
+ }
+ }
+ }
+
+ if (status) {
+ if(log.isDebugEnabled()){
+ log.debug("User '" + authorizedUser.getUserName() + "' is authorized");
+ }
+ return true;
+ }
+
+ if(log.isDebugEnabled()){
+ log.debug("No permissions associated for the user " + authorizedUser.getUserName());
+ }
+ return false;
+
+ } catch (UserStoreException e) {
+ //Log and return since we do not want to stop issuing the token in case of scope validation failures.
+ log.error("Error when getting the tenant's UserStoreManager or when getting roles of user ", e);
+ return false;
+ }
+ }
+
+}
diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/RoleBasedScopeValidator.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/RoleBasedScopeValidator.java
new file mode 100644
index 0000000000..593d9d0c89
--- /dev/null
+++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/RoleBasedScopeValidator.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2013, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. 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.device.mgt.oauth.extensions.validators;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.base.MultitenantConstants;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.device.mgt.oauth.extensions.internal.OAuthExtensionsDataHolder;
+import org.wso2.carbon.identity.application.common.model.User;
+import org.wso2.carbon.identity.base.IdentityConstants;
+import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
+import org.wso2.carbon.identity.core.util.IdentityUtil;
+import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
+import org.wso2.carbon.identity.oauth2.dao.TokenMgtDAO;
+import org.wso2.carbon.identity.oauth2.model.AccessTokenDO;
+import org.wso2.carbon.identity.oauth2.validators.OAuth2ScopeValidator;
+import org.wso2.carbon.user.api.UserStoreException;
+import org.wso2.carbon.user.api.UserStoreManager;
+import org.wso2.carbon.user.core.service.RealmService;
+import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * The JDBC Scope Validation implementation. This validates the Resource's scope (stored in IDN_OAUTH2_RESOURCE_SCOPE)
+ * against the Access Token's scopes.
+ */
+public class RoleBasedScopeValidator extends OAuth2ScopeValidator {
+
+ Log log = LogFactory.getLog(RoleBasedScopeValidator.class);
+
+ @Override
+ public boolean validateScope(AccessTokenDO accessTokenDO, String resourceScope) throws IdentityOAuth2Exception {
+
+ //Get the list of scopes associated with the access token
+ String[] scopes = accessTokenDO.getScope();
+
+ //If no scopes are associated with the token
+ if (scopes == null || scopes.length == 0) {
+ return true;
+ }
+
+ TokenMgtDAO tokenMgtDAO = new TokenMgtDAO();
+
+ List scopeList = new ArrayList<>(Arrays.asList(scopes));
+
+ //If the access token does not bear the scope required for accessing the Resource.
+ if(!scopeList.contains(resourceScope)){
+ if(log.isDebugEnabled() && IdentityUtil.isTokenLoggable(IdentityConstants.IdentityTokens.ACCESS_TOKEN)){
+ log.debug("Access token '" + accessTokenDO.getAccessToken() + "' does not bear the scope '" +
+ resourceScope + "'");
+ }
+ return false;
+ }
+
+ try {
+ //Get the roles associated with the scope, if any
+ Set rolesOfScope = tokenMgtDAO.getRolesOfScopeByScopeKey(resourceScope);
+
+ //If the scope doesn't have any roles associated with it.
+ if(rolesOfScope == null || rolesOfScope.isEmpty()){
+ if(log.isDebugEnabled()){
+ log.debug("Did not find any roles associated to the scope " + resourceScope);
+ }
+ return true;
+ }
+
+ if(log.isDebugEnabled()){
+ StringBuilder logMessage = new StringBuilder("Found roles of scope '" + resourceScope + "' ");
+ for(String role : rolesOfScope){
+ logMessage.append(role);
+ logMessage.append(", ");
+ }
+ log.debug(logMessage.toString());
+ }
+
+ User authzUser = accessTokenDO.getAuthzUser();
+ RealmService realmService = OAuthExtensionsDataHolder.getInstance().getRealmService();
+
+ int tenantId = realmService.getTenantManager().
+ getTenantId(authzUser.getTenantDomain());
+
+ if (tenantId == 0 || tenantId == -1) {
+ tenantId = IdentityTenantUtil.getTenantIdOfUser(authzUser.getUserName());
+ }
+
+ UserStoreManager userStoreManager;
+ String[] userRoles;
+ boolean tenantFlowStarted = false;
+
+ try{
+ //If this is a tenant user
+ if(tenantId != MultitenantConstants.SUPER_TENANT_ID){
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
+ realmService.getTenantManager().getDomain(tenantId),true);
+ tenantFlowStarted = true;
+ }
+
+ userStoreManager = realmService.getTenantUserRealm(tenantId).getUserStoreManager();
+ userRoles = userStoreManager.getRoleListOfUser(
+ MultitenantUtils.getTenantAwareUsername(authzUser.getUserName()));
+ } finally {
+ if (tenantFlowStarted) {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+
+ if(userRoles != null && userRoles.length > 0){
+ if(log.isDebugEnabled()){
+ StringBuilder logMessage = new StringBuilder("Found roles of user ");
+ logMessage.append(authzUser.getUserName());
+ logMessage.append(" ");
+ for(String role : userRoles){
+ logMessage.append(role);
+ logMessage.append(", ");
+ }
+ log.debug(logMessage.toString());
+ }
+ //Check if the user still has a valid role for this scope.
+ rolesOfScope.retainAll(Arrays.asList(userRoles));
+ return !rolesOfScope.isEmpty();
+ }
+ else{
+ if(log.isDebugEnabled()){
+ log.debug("No roles associated for the user " + authzUser.getUserName());
+ }
+ return false;
+ }
+
+ } catch (UserStoreException e) {
+ //Log and return since we do not want to stop issuing the token in case of scope validation failures.
+ log.error("Error when getting the tenant's UserStoreManager or when getting roles of user ", e);
+ return false;
+ }
+ }
+}
diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/BasicAuthAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/BasicAuthAuthenticator.java
index 908613cf35..3b06468fe9 100644
--- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/BasicAuthAuthenticator.java
+++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/BasicAuthAuthenticator.java
@@ -28,6 +28,7 @@ import org.apache.tomcat.util.buf.CharChunk;
import org.apache.tomcat.util.buf.MessageBytes;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
+import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import org.wso2.carbon.webapp.authenticator.framework.AuthenticationException;
import org.wso2.carbon.webapp.authenticator.framework.AuthenticatorFrameworkDataHolder;
import org.wso2.carbon.webapp.authenticator.framework.Constants;
@@ -68,7 +69,8 @@ public class BasicAuthAuthenticator implements WebappAuthenticator {
int tenantId = Utils.getTenantIdOFUser(credentials.getUsername());
UserStoreManager userStore = AuthenticatorFrameworkDataHolder.getInstance().getRealmService().
getTenantUserRealm(tenantId).getUserStoreManager();
- boolean authenticated = userStore.authenticate(credentials.getUsername(), credentials.getPassword());
+ String username = MultitenantUtils.getTenantAwareUsername(credentials.getUsername());
+ boolean authenticated = userStore.authenticate(username, credentials.getPassword());
if (authenticated) {
authenticationInfo.setStatus(Status.CONTINUE);
authenticationInfo.setUsername(credentials.getUsername());
diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/h2.sql b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/h2.sql
index eb30a07b12..498a439c07 100644
--- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/h2.sql
+++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/h2.sql
@@ -145,12 +145,7 @@ CREATE TABLE IF NOT EXISTS DM_PROFILE (
DEVICE_TYPE VARCHAR(300) NOT NULL ,
CREATED_TIME DATETIME NOT NULL ,
UPDATED_TIME DATETIME NOT NULL ,
- PRIMARY KEY (ID) ,
- CONSTRAINT DM_PROFILE_DEVICE_TYPE
- FOREIGN KEY (DEVICE_TYPE, TENANT_ID)
- REFERENCES DM_DEVICE_TYPE (NAME, PROVIDER_TENANT_ID)
- ON DELETE NO ACTION
- ON UPDATE NO ACTION
+ PRIMARY KEY (ID)
);
CREATE TABLE IF NOT EXISTS DM_POLICY (
diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mssql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mssql.sql
index 82dba1d770..ed33177429 100644
--- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mssql.sql
+++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mssql.sql
@@ -191,9 +191,7 @@ CREATE TABLE DM_PROFILE (
DEVICE_TYPE VARCHAR(300) NOT NULL ,
CREATED_TIME DATETIME NOT NULL ,
UPDATED_TIME DATETIME NOT NULL ,
- PRIMARY KEY (ID) ,
- CONSTRAINT DM_PROFILE_DEVICE_TYPE FOREIGN KEY (DEVICE_TYPE, TENANT_ID) REFERENCES
- DM_DEVICE_TYPE (NAME, PROVIDER_TENANT_ID) ON DELETE NO ACTION ON UPDATE NO ACTION
+ PRIMARY KEY (ID)
);
IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_POLICY]') AND TYPE IN (N'U'))
diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mysql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mysql.sql
index e1a960351d..6bec98fc5b 100644
--- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mysql.sql
+++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/mysql.sql
@@ -168,12 +168,7 @@ CREATE TABLE IF NOT EXISTS DM_PROFILE (
DEVICE_TYPE VARCHAR(300) NOT NULL ,
CREATED_TIME DATETIME NOT NULL ,
UPDATED_TIME DATETIME NOT NULL ,
- PRIMARY KEY (ID) ,
- CONSTRAINT DM_PROFILE_DEVICE_TYPE
- FOREIGN KEY (DEVICE_TYPE, TENANT_ID)
- REFERENCES DM_DEVICE_TYPE (NAME, PROVIDER_TENANT_ID)
- ON DELETE NO ACTION
- ON UPDATE NO ACTION
+ PRIMARY KEY (ID)
)ENGINE = InnoDB;
diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/oracle.sql b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/oracle.sql
index 5e4836b01e..4bd5f55de9 100644
--- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/oracle.sql
+++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/oracle.sql
@@ -268,10 +268,7 @@ CREATE TABLE DM_PROFILE (
DEVICE_TYPE VARCHAR2(300) NOT NULL ,
CREATED_TIME TIMESTAMP(0) NOT NULL ,
UPDATED_TIME TIMESTAMP(0) NOT NULL ,
- CONSTRAINT PK_DM_PROFILE PRIMARY KEY (ID) ,
- CONSTRAINT DM_PROFILE_DEVICE_TYPE
- FOREIGN KEY (DEVICE_TYPE, TENANT_ID)
- REFERENCES DM_DEVICE_TYPE (NAME, PROVIDER_TENANT_ID)
+ CONSTRAINT PK_DM_PROFILE PRIMARY KEY (ID)
)
/
-- Generate ID using sequence and trigger
diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/postgresql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/postgresql.sql
index f1e3549226..a4f07d7781 100644
--- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/postgresql.sql
+++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/dbscripts/cdm/postgresql.sql
@@ -148,12 +148,7 @@ CREATE TABLE IF NOT EXISTS DM_PROFILE (
TENANT_ID INTEGER NOT NULL ,
DEVICE_TYPE VARCHAR(300) NOT NULL ,
CREATED_TIME TIMESTAMP NOT NULL ,
- UPDATED_TIME TIMESTAMP NOT NULL ,
- CONSTRAINT DM_PROFILE_DEVICE_TYPE
- FOREIGN KEY (DEVICE_TYPE, TENANT_ID)
- REFERENCES DM_DEVICE_TYPE (NAME, PROVIDER_TENANT_ID)
- ON DELETE NO ACTION
- ON UPDATE NO ACTION
+ UPDATED_TIME TIMESTAMP NOT NULL
);
CREATE TABLE IF NOT EXISTS DM_POLICY (