Refactored and fixed findbug issues in OAuth extension

revert-70aa11f8
mharindu 9 years ago
parent 04fa0f4874
commit c824e63f1e

@ -46,7 +46,14 @@ public class OAuthExtUtils {
private static final Log log = LogFactory.getLog(OAuthExtUtils.class); private static final Log log = LogFactory.getLog(OAuthExtUtils.class);
private static final String DEFAULT_SCOPE_NAME = "default"; private static final String DEFAULT_SCOPE_NAME = "default";
private static final String UI_EXECUTE = "ui.execute"; private static final String UI_EXECUTE = "ui.execute";
private static final String REST_API_SCOPE_CACHE = "REST_API_SCOPE_CACHE";
/**
* This method is used to get the tenant id when given tenant domain.
*
* @param tenantDomain Tenant domain name.
* @return Returns the tenant id.
*/
public static int getTenantId(String tenantDomain) { public static int getTenantId(String tenantDomain) {
int tenantId = 0; int tenantId = 0;
if (tenantDomain != null) { if (tenantDomain != null) {
@ -62,9 +69,16 @@ public class OAuthExtUtils {
return tenantId; return tenantId;
} }
/**
* This method is used to set scopes that are authorized to the OAuth token request message context.
*
* @param tokReqMsgCtx OAuth token request message context
* @return Returns true if success.
*/
public static boolean setScopes(OAuthTokenReqMessageContext tokReqMsgCtx) { public static boolean setScopes(OAuthTokenReqMessageContext tokReqMsgCtx) {
String[] requestedScopes = tokReqMsgCtx.getScope(); String[] requestedScopes = tokReqMsgCtx.getScope();
String[] defaultScope = new String[]{DEFAULT_SCOPE_NAME}; String[] defaultScope = new String[]{DEFAULT_SCOPE_NAME};
//If no scopes were requested. //If no scopes were requested.
if (requestedScopes == null || requestedScopes.length == 0) { if (requestedScopes == null || requestedScopes.length == 0) {
tokReqMsgCtx.setScope(defaultScope); tokReqMsgCtx.setScope(defaultScope);
@ -72,7 +86,6 @@ public class OAuthExtUtils {
} }
String consumerKey = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId(); String consumerKey = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId();
String username = tokReqMsgCtx.getAuthorizedUser().getUserName();
List<String> reqScopeList = Arrays.asList(requestedScopes); List<String> reqScopeList = Arrays.asList(requestedScopes);
Map<String, String> restAPIScopesOfCurrentTenant; Map<String, String> restAPIScopesOfCurrentTenant;
@ -80,23 +93,27 @@ public class OAuthExtUtils {
Map<String, String> appScopes; Map<String, String> appScopes;
ApiMgtDAO apiMgtDAO = new ApiMgtDAO(); ApiMgtDAO apiMgtDAO = new ApiMgtDAO();
//Get all the scopes and roles against the scopes defined for the APIs subscribed to the application.
//Get all the scopes and permissions against the scopes defined for the APIs subscribed to the application.
appScopes = apiMgtDAO.getScopeRolesOfApplication(consumerKey); appScopes = apiMgtDAO.getScopeRolesOfApplication(consumerKey);
//Add API Manager rest API scopes set. This list should be loaded at server start up and keep //Add API Manager rest API scopes set. This list should be loaded at server start up and keep
//in memory and add it to each and every request coming. //in memory and add it to each and every request coming.
String tenantDomain = tokReqMsgCtx.getAuthorizedUser().getTenantDomain(); String tenantDomain = tokReqMsgCtx.getAuthorizedUser().getTenantDomain();
restAPIScopesOfCurrentTenant = (Map) Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER) restAPIScopesOfCurrentTenant = (Map) Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER)
.getCache("REST_API_SCOPE_CACHE") .getCache(REST_API_SCOPE_CACHE)
.get(tenantDomain); .get(tenantDomain);
if (restAPIScopesOfCurrentTenant != null) { if (restAPIScopesOfCurrentTenant != null) {
appScopes.putAll(restAPIScopesOfCurrentTenant); appScopes.putAll(restAPIScopesOfCurrentTenant);
} else { } else {
restAPIScopesOfCurrentTenant = APIUtil.getRESTAPIScopesFromConfig(APIUtil.getTenantRESTAPIScopesConfig(tenantDomain)); restAPIScopesOfCurrentTenant = APIUtil.
getRESTAPIScopesFromConfig(APIUtil.getTenantRESTAPIScopesConfig(tenantDomain));
//call load tenant config for rest API. //call load tenant config for rest API.
//then put cache //then put cache
appScopes.putAll(restAPIScopesOfCurrentTenant); appScopes.putAll(restAPIScopesOfCurrentTenant);
Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER) Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER)
.getCache("REST_API_SCOPE_CACHE") .getCache(REST_API_SCOPE_CACHE)
.put(tenantDomain, restAPIScopesOfCurrentTenant); .put(tenantDomain, restAPIScopesOfCurrentTenant);
} }
//If no scopes can be found in the context of the application //If no scopes can be found in the context of the application
@ -111,7 +128,80 @@ public class OAuthExtUtils {
return true; return true;
} }
// check for authorized scopes
List<String> authorizedScopes = getAuthorizedScopes(tokReqMsgCtx, reqScopeList, appScopes);
if (!authorizedScopes.isEmpty()) {
String[] authScopesArr = authorizedScopes.toArray(new String[authorizedScopes.size()]);
tokReqMsgCtx.setScope(authScopesArr);
} else {
tokReqMsgCtx.setScope(defaultScope);
}
} catch (APIManagementException e) {
log.error("Error while getting scopes of application " + e.getMessage());
return false;
}
return true;
}
/**
* Determines if the scope is specified in the white list.
*
* @param scope - The scope key to check
* @return - 'true' if the scope is white listed. 'false' if not.
*/
private static boolean isWhiteListedScope(String scope) {
// load white listed scopes
List<String> scopeSkipList = OAuthExtensionsDataHolder.getInstance().getWhitelistedScopes();
for (String scopeTobeSkipped : scopeSkipList) {
if (scope.matches(scopeTobeSkipped)) {
return true;
}
}
return false;
}
/**
* Get the set of default scopes. If a requested scope is matches with the patterns specified in the white list,
* then such scopes will be issued without further validation. If the scope list is empty,
* token will be issued for default scope.
*
* @param requestedScopes - The set of requested scopes
* @return - The subset of scopes that are allowed
*/
private static String[] getAllowedScopes(List<String> requestedScopes) {
List<String> authorizedScopes = new ArrayList<>();
//Iterate the requested scopes list.
for (String scope : requestedScopes) {
if (isWhiteListedScope(scope)) {
authorizedScopes.add(scope);
}
}
if (authorizedScopes.isEmpty()) {
authorizedScopes.add(DEFAULT_SCOPE_NAME);
}
return authorizedScopes.toArray(new String[authorizedScopes.size()]);
}
/**
* This method is used to get the authorized scopes out of requested scopes. It checks requested scopes with app
* scopes whether user has permissions to take actions for the requested scopes.
*
* @param tokReqMsgCtx OAuth token request message context.
* @param reqScopeList Requested scope list.
* @param appScopes App scopes.
* @return Returns a list of scopes.
*/
private static List<String> getAuthorizedScopes(OAuthTokenReqMessageContext tokReqMsgCtx, List<String> reqScopeList,
Map<String, String> appScopes) {
boolean status;
List<String> authorizedScopes = new ArrayList<>();
int tenantId; int tenantId;
String username = tokReqMsgCtx.getAuthorizedUser().getUserName();
String tenantDomain = tokReqMsgCtx.getAuthorizedUser().getTenantDomain();
RealmService realmService = OAuthExtensionsDataHolder.getInstance().getRealmService(); RealmService realmService = OAuthExtensionsDataHolder.getInstance().getRealmService();
try { try {
@ -122,26 +212,20 @@ public class OAuthExtUtils {
tenantId = IdentityTenantUtil.getTenantIdOfUser(username); tenantId = IdentityTenantUtil.getTenantIdOfUser(username);
} }
} 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;
}
UserRealm userRealm = OAuthExtensionsDataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId); UserRealm userRealm = OAuthExtensionsDataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId);
List<String> authorizedScopes = new ArrayList<>();
boolean status;
//List<String> userRoleList = new ArrayList<>(Arrays.asList(userRoles));
//Iterate the requested scopes list. //Iterate the requested scopes list.
for (String scope : reqScopeList) { for (String scope : reqScopeList) {
status = false; status = false;
//Get the set of roles associated with the requested scope. //Get the set of roles associated with the requested scope.
String appPermissions = appScopes.get(scope); String appPermissions = appScopes.get(scope);
//If the scope has been defined in the context of the App and if roles have been defined for the scope
//If the scope has been defined in the context of the App and if permissions have been defined for the scope
if (appPermissions != null && appPermissions.length() != 0) { if (appPermissions != null && appPermissions.length() != 0) {
List<String> permissions = new ArrayList<>(Arrays.asList(appPermissions.replaceAll(" ", "").split(","))); List<String> permissions = new ArrayList<>(Arrays.asList(appPermissions.replaceAll(" ", "").split(",")));
//Check if user has at least one of the roles associated with the scope
//Check if user has at least one of the permission associated with the scope
if (!permissions.isEmpty()) { if (!permissions.isEmpty()) {
for (String permission : permissions) { for (String permission : permissions) {
if (userRealm != null && userRealm.getAuthorizationManager() != null) { if (userRealm != null && userRealm.getAuthorizationManager() != null) {
@ -164,66 +248,16 @@ public class OAuthExtUtils {
} }
} }
} }
//The requested scope is defined for the context of the App but no roles have been associated with the scope
//OR
//The scope string starts with 'device_'. //The scope string starts with 'device_'.
else if (appScopes.containsKey(scope) || isWhiteListedScope(scope)) { else if (appScopes.containsKey(scope) || isWhiteListedScope(scope)) {
authorizedScopes.add(scope); authorizedScopes.add(scope);
} }
} }
if (!authorizedScopes.isEmpty()) {
String[] authScopesArr = authorizedScopes.toArray(new String[authorizedScopes.size()]);
tokReqMsgCtx.setScope(authScopesArr);
} else {
tokReqMsgCtx.setScope(defaultScope);
}
} catch (APIManagementException e) {
log.error("Error while getting scopes of application " + e.getMessage());
return false;
} catch (UserStoreException e) { } catch (UserStoreException e) {
e.printStackTrace(); log.error("Error occurred while initializing user store.", e);
}
return true;
} }
return authorizedScopes;
/**
* Determines if the scope is specified in the whitelist.
*
* @param scope - The scope key to check
* @return - 'true' if the scope is white listed. 'false' if not.
*/
public static boolean isWhiteListedScope(String scope) {
// load white listed scopes
List<String> scopeSkipList = OAuthExtensionsDataHolder.getInstance().getWhitelistedScopes();
for (String scopeTobeSkipped : scopeSkipList) {
if (scope.matches(scopeTobeSkipped)) {
return true;
}
}
return false;
}
/**
* Get the set of default scopes. If a requested scope is matches with the patterns specified in the whitelist,
* then such scopes will be issued without further validation. If the scope list is empty,
* token will be issued for default scope.
*
* @param requestedScopes - The set of requested scopes
* @return - The subset of scopes that are allowed
*/
private static String[] getAllowedScopes(List<String> requestedScopes) {
List<String> authorizedScopes = new ArrayList<String>();
//Iterate the requested scopes list.
for (String scope : requestedScopes) {
if (isWhiteListedScope(scope)) {
authorizedScopes.add(scope);
}
}
if (authorizedScopes.isEmpty()) {
authorizedScopes.add(DEFAULT_SCOPE_NAME);
}
return authorizedScopes.toArray(new String[authorizedScopes.size()]);
} }
} }

@ -42,12 +42,7 @@ import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.user.core.util.UserCoreUtil; import org.wso2.carbon.user.core.util.UserCoreUtil;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -68,7 +63,7 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
private static final String EMAIL_LOGIN = "EmailLogin"; private static final String EMAIL_LOGIN = "EmailLogin";
private static final String PRIMARY_LOGIN = "primary"; private static final String PRIMARY_LOGIN = "primary";
private Map<String,Map<String,String>> loginConfiguration = new ConcurrentHashMap<>(); private Map<String, Map<String, String>> loginConfiguration = new ConcurrentHashMap<>();
private List<String> requiredHeaderClaimUris = new ArrayList<>(); private List<String> requiredHeaderClaimUris = new ArrayList<>();
@ -103,7 +98,7 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
boolean isValidated = super.validateGrant(tokReqMsgCtx); boolean isValidated = super.validateGrant(tokReqMsgCtx);
if(isValidated){ if (isValidated) {
int tenantId; int tenantId;
tenantId = IdentityTenantUtil.getTenantIdOfUser(username); tenantId = IdentityTenantUtil.getTenantIdOfUser(username);
@ -120,20 +115,17 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
List<ResponseHeader> respHeaders = new ArrayList<>(); List<ResponseHeader> respHeaders = new ArrayList<>();
if (oAuth2AccessTokenReqDTO.getResourceOwnerUsername() != null) { if (oAuth2AccessTokenReqDTO.getResourceOwnerUsername() != null) {
try { try {
if (requiredHeaderClaimUris != null && !requiredHeaderClaimUris.isEmpty()) { if (requiredHeaderClaimUris != null && !requiredHeaderClaimUris.isEmpty()) {
// Get user's claim values from the default profile. // Get user's claim values from the default profile.
String userStoreDomain = tokReqMsgCtx.getAuthorizedUser().getUserStoreDomain(); String userStoreDomain = tokReqMsgCtx.getAuthorizedUser().getUserStoreDomain();
String endUsernameWithDomain = UserCoreUtil.addDomainToName String endUsernameWithDomain = UserCoreUtil.
(oAuth2AccessTokenReqDTO.getResourceOwnerUsername(), addDomainToName(oAuth2AccessTokenReqDTO.getResourceOwnerUsername(), userStoreDomain);
userStoreDomain);
Claim[] mapClaimValues = getUserClaimValues(endUsernameWithDomain,userStoreManager); Claim[] mapClaimValues = getUserClaimValues(endUsernameWithDomain, userStoreManager);
if(mapClaimValues != null && mapClaimValues.length > 0){ if (mapClaimValues != null && mapClaimValues.length > 0) {
ResponseHeader header; ResponseHeader header;
for (String claimUri : requiredHeaderClaimUris) { for (String claimUri : requiredHeaderClaimUris) {
for (Claim claim : mapClaimValues) { for (Claim claim : mapClaimValues) {
@ -146,26 +138,22 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
} }
} }
} }
} else if (log.isDebugEnabled()) {
log.debug("No claim values for user : " + endUsernameWithDomain);
} }
else if(log.isDebugEnabled()){
log.debug("No claim values for user : "+endUsernameWithDomain);
}
} }
} catch (Exception e) { } catch (Exception e) {
throw new IdentityOAuth2Exception(e.getMessage(), e); throw new IdentityOAuth2Exception("Error occurred while retrieving user claims", e);
} }
} }
tokReqMsgCtx.addProperty("RESPONSE_HEADERS", respHeaders.toArray(new ResponseHeader[respHeaders.size()]));
tokReqMsgCtx.addProperty("RESPONSE_HEADERS", respHeaders.toArray(
new ResponseHeader[respHeaders.size()]));
} }
return isValidated; return isValidated;
} }
@Override @Override
public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx){ public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) {
return OAuthExtUtils.setScopes(tokReqMsgCtx); return OAuthExtUtils.setScopes(tokReqMsgCtx);
} }
@ -191,17 +179,14 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
Map<String, String> emailConf = loginConfiguration.get(EMAIL_LOGIN); Map<String, String> emailConf = loginConfiguration.get(EMAIL_LOGIN);
if ("true".equalsIgnoreCase(emailConf.get(PRIMARY_LOGIN))) { if ("true".equalsIgnoreCase(emailConf.get(PRIMARY_LOGIN))) {
return !isUserLoggedInEmail(userId); return !isUserLoggedInEmail(userId);
} } else if ("false".equalsIgnoreCase(emailConf.get(PRIMARY_LOGIN))) {
else if ("false".equalsIgnoreCase(emailConf.get(PRIMARY_LOGIN))) {
return isUserLoggedInEmail(userId); return isUserLoggedInEmail(userId);
} }
} } else if (loginConfiguration.get(USERID_LOGIN) != null) {
else if (loginConfiguration.get(USERID_LOGIN) != null) {
Map<String, String> userIdConf = loginConfiguration.get(USERID_LOGIN); Map<String, String> userIdConf = loginConfiguration.get(USERID_LOGIN);
if ("true".equalsIgnoreCase(userIdConf.get(PRIMARY_LOGIN))) { if ("true".equalsIgnoreCase(userIdConf.get(PRIMARY_LOGIN))) {
return isUserLoggedInEmail(userId); return isUserLoggedInEmail(userId);
} } else if ("false".equalsIgnoreCase(userIdConf.get(PRIMARY_LOGIN))) {
else if ("false".equalsIgnoreCase(userIdConf.get(PRIMARY_LOGIN))) {
return !isUserLoggedInEmail(userId); return !isUserLoggedInEmail(userId);
} }
} }
@ -258,20 +243,22 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
throws throws
UserStoreException { UserStoreException {
Claim[] userClaims = userClaimsCache.getValueFromCache(authorizedUser); Claim[] userClaims = userClaimsCache.getValueFromCache(authorizedUser);
if(userClaims != null){ if (userClaims != null) {
return userClaims; return userClaims;
}else{ } else {
if(log.isDebugEnabled()){ if (log.isDebugEnabled()) {
log.debug("Cache miss for user claims. Username :" + authorizedUser); log.debug("Cache miss for user claims. Username :" + authorizedUser);
} }
userClaims = userStoreManager.getUserClaimValues( userClaims = userStoreManager.getUserClaimValues(
authorizedUser, null); authorizedUser, null);
userClaimsCache.addToCache(authorizedUser,userClaims); userClaimsCache.addToCache(authorizedUser, userClaims);
return userClaims; return userClaims;
} }
} }
// Read the required claim configuration from identity.xml /**
* Read the required claim configuration from identity.xml
*/
private void parseRequiredHeaderClaimUris(OMElement requiredClaimUrisElem) { private void parseRequiredHeaderClaimUris(OMElement requiredClaimUrisElem) {
if (requiredClaimUrisElem == null) { if (requiredClaimUrisElem == null) {
return; return;
@ -302,6 +289,7 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
* </LoginConfig> * </LoginConfig>
* ..... * .....
* </OAuth> * </OAuth>
*
* @param oauthConfigElem - The '<LoginConfig>' xml configuration element in the api-manager.xml * @param oauthConfigElem - The '<LoginConfig>' xml configuration element in the api-manager.xml
*/ */
private void parseLoginConfig(OMElement oauthConfigElem) { private void parseLoginConfig(OMElement oauthConfigElem) {

Loading…
Cancel
Save