mirror of
https://repository.entgra.net/community/device-mgt-core.git
synced 2025-10-06 02:01:45 +00:00
Merge pull request #573 from milanperera/cloud
Fixed multi tenancy issues related to android device type and implemented a scope validation delegator
This commit is contained in:
commit
de47812d6d
@ -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);
|
||||
|
||||
@ -37,14 +37,14 @@
|
||||
</Permission>
|
||||
<Permission>
|
||||
<name>Register application</name>
|
||||
<path>/device-mgt/api/application</path>
|
||||
<path>/manage/api/subscribe</path>
|
||||
<url>/register</url>
|
||||
<method>POST</method>
|
||||
<scope>application_user</scope>
|
||||
</Permission>
|
||||
<Permission>
|
||||
<name>Delete application</name>
|
||||
<path>/device-mgt/api/application</path>
|
||||
<path>/manage/api/subscribe</path>
|
||||
<url>/unregister</url>
|
||||
<method>DELETE</method>
|
||||
<scope>application_user</scope>
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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<String, OAuth2ScopeValidator> 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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -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<String> whitelistedScopes;
|
||||
private Map<String, OAuth2ScopeValidator> 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<String, OAuth2ScopeValidator> getScopeValidators() {
|
||||
return scopeValidators;
|
||||
}
|
||||
|
||||
public void setScopeValidators(Map<String, OAuth2ScopeValidator> scopeValidators) {
|
||||
this.scopeValidators = scopeValidators;
|
||||
}
|
||||
|
||||
public void addScopeValidator(OAuth2ScopeValidator oAuth2ScopeValidator, String prefix) {
|
||||
scopeValidators.put(prefix, oAuth2ScopeValidator);
|
||||
}
|
||||
|
||||
public void removeScopeValidator() {
|
||||
scopeValidators = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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<String> 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<String> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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<String> 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<String> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
|
||||
@ -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 (
|
||||
|
||||
@ -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'))
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 (
|
||||
|
||||
Loading…
Reference in New Issue
Block a user