Refactored and fixed findbug issues in OAuth extension

4.x.x
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 String DEFAULT_SCOPE_NAME = "default";
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) {
int tenantId = 0;
if (tenantDomain != null) {
@ -62,9 +69,16 @@ public class OAuthExtUtils {
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) {
String[] requestedScopes = tokReqMsgCtx.getScope();
String[] defaultScope = new String[]{DEFAULT_SCOPE_NAME};
//If no scopes were requested.
if (requestedScopes == null || requestedScopes.length == 0) {
tokReqMsgCtx.setScope(defaultScope);
@ -72,7 +86,6 @@ public class OAuthExtUtils {
}
String consumerKey = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId();
String username = tokReqMsgCtx.getAuthorizedUser().getUserName();
List<String> reqScopeList = Arrays.asList(requestedScopes);
Map<String, String> restAPIScopesOfCurrentTenant;
@ -80,23 +93,27 @@ public class OAuthExtUtils {
Map<String, String> appScopes;
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);
//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.
String tenantDomain = tokReqMsgCtx.getAuthorizedUser().getTenantDomain();
restAPIScopesOfCurrentTenant = (Map) Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER)
.getCache("REST_API_SCOPE_CACHE")
.getCache(REST_API_SCOPE_CACHE)
.get(tenantDomain);
if (restAPIScopesOfCurrentTenant != null) {
appScopes.putAll(restAPIScopesOfCurrentTenant);
} else {
restAPIScopesOfCurrentTenant = APIUtil.getRESTAPIScopesFromConfig(APIUtil.getTenantRESTAPIScopesConfig(tenantDomain));
restAPIScopesOfCurrentTenant = APIUtil.
getRESTAPIScopesFromConfig(APIUtil.getTenantRESTAPIScopesConfig(tenantDomain));
//call load tenant config for rest API.
//then put cache
appScopes.putAll(restAPIScopesOfCurrentTenant);
Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER)
.getCache("REST_API_SCOPE_CACHE")
.getCache(REST_API_SCOPE_CACHE)
.put(tenantDomain, restAPIScopesOfCurrentTenant);
}
//If no scopes can be found in the context of the application
@ -111,66 +128,9 @@ public class OAuthExtUtils {
return true;
}
int tenantId;
RealmService realmService = OAuthExtensionsDataHolder.getInstance().getRealmService();
try {
tenantId = realmService.getTenantManager().getTenantId(tenantDomain);
// If tenant Id is not set in the tokenReqContext, deriving it from username.
if (tenantId == 0 || tenantId == -1) {
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);
List<String> authorizedScopes = new ArrayList<>();
boolean status;
//List<String> userRoleList = new ArrayList<>(Arrays.asList(userRoles));
// check for authorized scopes
List<String> authorizedScopes = getAuthorizedScopes(tokReqMsgCtx, reqScopeList, appScopes);
//Iterate the requested scopes list.
for (String scope : reqScopeList) {
status = false;
//Get the set of roles associated with the requested 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 (appPermissions != null && appPermissions.length() != 0) {
List<String> permissions = new ArrayList<>(Arrays.asList(appPermissions.replaceAll(" ", "").split(",")));
//Check if user has at least one of the roles associated with the scope
if (!permissions.isEmpty()) {
for (String permission : permissions) {
if (userRealm != null && userRealm.getAuthorizationManager() != null) {
String userStore = tokReqMsgCtx.getAuthorizedUser().getUserStoreDomain();
if (userStore != null) {
status = userRealm.getAuthorizationManager()
.isUserAuthorized(userStore + "/" + username, permission, UI_EXECUTE);
} else {
status = userRealm.getAuthorizationManager()
.isUserAuthorized(username, permission, UI_EXECUTE);
}
if (status) {
break;
}
}
}
if (status) {
authorizedScopes.add(scope);
}
}
}
//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_'.
else if (appScopes.containsKey(scope) || isWhiteListedScope(scope)) {
authorizedScopes.add(scope);
}
}
if (!authorizedScopes.isEmpty()) {
String[] authScopesArr = authorizedScopes.toArray(new String[authorizedScopes.size()]);
tokReqMsgCtx.setScope(authScopesArr);
@ -180,19 +140,17 @@ public class OAuthExtUtils {
} catch (APIManagementException e) {
log.error("Error while getting scopes of application " + e.getMessage());
return false;
} catch (UserStoreException e) {
e.printStackTrace();
}
return true;
}
/**
* Determines if the scope is specified in the whitelist.
* 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.
*/
public static boolean isWhiteListedScope(String scope) {
private static boolean isWhiteListedScope(String scope) {
// load white listed scopes
List<String> scopeSkipList = OAuthExtensionsDataHolder.getInstance().getWhitelistedScopes();
for (String scopeTobeSkipped : scopeSkipList) {
@ -204,7 +162,7 @@ public class OAuthExtUtils {
}
/**
* Get the set of default scopes. If a requested scope is matches with the patterns specified in the whitelist,
* 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.
*
@ -212,7 +170,7 @@ public class OAuthExtUtils {
* @return - The subset of scopes that are allowed
*/
private static String[] getAllowedScopes(List<String> requestedScopes) {
List<String> authorizedScopes = new ArrayList<String>();
List<String> authorizedScopes = new ArrayList<>();
//Iterate the requested scopes list.
for (String scope : requestedScopes) {
@ -226,4 +184,80 @@ public class OAuthExtUtils {
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;
String username = tokReqMsgCtx.getAuthorizedUser().getUserName();
String tenantDomain = tokReqMsgCtx.getAuthorizedUser().getTenantDomain();
RealmService realmService = OAuthExtensionsDataHolder.getInstance().getRealmService();
try {
tenantId = realmService.getTenantManager().getTenantId(tenantDomain);
// If tenant Id is not set in the tokenReqContext, deriving it from username.
if (tenantId == 0 || tenantId == -1) {
tenantId = IdentityTenantUtil.getTenantIdOfUser(username);
}
UserRealm userRealm = OAuthExtensionsDataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId);
//Iterate the requested scopes list.
for (String scope : reqScopeList) {
status = false;
//Get the set of roles associated with the requested scope.
String appPermissions = appScopes.get(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) {
List<String> permissions = new ArrayList<>(Arrays.asList(appPermissions.replaceAll(" ", "").split(",")));
//Check if user has at least one of the permission associated with the scope
if (!permissions.isEmpty()) {
for (String permission : permissions) {
if (userRealm != null && userRealm.getAuthorizationManager() != null) {
String userStore = tokReqMsgCtx.getAuthorizedUser().getUserStoreDomain();
if (userStore != null) {
status = userRealm.getAuthorizationManager()
.isUserAuthorized(userStore + "/" + username, permission, UI_EXECUTE);
} else {
status = userRealm.getAuthorizationManager()
.isUserAuthorized(username, permission, UI_EXECUTE);
}
if (status) {
break;
}
}
}
if (status) {
authorizedScopes.add(scope);
}
}
}
//The scope string starts with 'device_'.
else if (appScopes.containsKey(scope) || isWhiteListedScope(scope)) {
authorizedScopes.add(scope);
}
}
} catch (UserStoreException e) {
log.error("Error occurred while initializing user store.", e);
}
return authorizedScopes;
}
}

@ -42,12 +42,7 @@ import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.user.core.util.UserCoreUtil;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("unused")
@ -68,7 +63,7 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
private static final String EMAIL_LOGIN = "EmailLogin";
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<>();
@ -103,7 +98,7 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
boolean isValidated = super.validateGrant(tokReqMsgCtx);
if(isValidated){
if (isValidated) {
int tenantId;
tenantId = IdentityTenantUtil.getTenantIdOfUser(username);
@ -120,20 +115,17 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
List<ResponseHeader> respHeaders = new ArrayList<>();
if (oAuth2AccessTokenReqDTO.getResourceOwnerUsername() != null) {
try {
if (requiredHeaderClaimUris != null && !requiredHeaderClaimUris.isEmpty()) {
// Get user's claim values from the default profile.
String userStoreDomain = tokReqMsgCtx.getAuthorizedUser().getUserStoreDomain();
String endUsernameWithDomain = UserCoreUtil.addDomainToName
(oAuth2AccessTokenReqDTO.getResourceOwnerUsername(),
userStoreDomain);
String endUsernameWithDomain = UserCoreUtil.
addDomainToName(oAuth2AccessTokenReqDTO.getResourceOwnerUsername(), 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;
for (String claimUri : requiredHeaderClaimUris) {
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) {
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;
}
@Override
public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx){
public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) {
return OAuthExtUtils.setScopes(tokReqMsgCtx);
}
@ -183,7 +171,7 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
*
* @param userId - The username used to login.
* @return <code>true</code> if secondary login name is used,
* <code>false</code> if primary login name has been used
* <code>false</code> if primary login name has been used
*/
private boolean isSecondaryLogin(String userId) {
@ -191,17 +179,14 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
Map<String, String> emailConf = loginConfiguration.get(EMAIL_LOGIN);
if ("true".equalsIgnoreCase(emailConf.get(PRIMARY_LOGIN))) {
return !isUserLoggedInEmail(userId);
}
else if ("false".equalsIgnoreCase(emailConf.get(PRIMARY_LOGIN))) {
} else if ("false".equalsIgnoreCase(emailConf.get(PRIMARY_LOGIN))) {
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);
if ("true".equalsIgnoreCase(userIdConf.get(PRIMARY_LOGIN))) {
return isUserLoggedInEmail(userId);
}
else if ("false".equalsIgnoreCase(userIdConf.get(PRIMARY_LOGIN))) {
} else if ("false".equalsIgnoreCase(userIdConf.get(PRIMARY_LOGIN))) {
return !isUserLoggedInEmail(userId);
}
}
@ -258,20 +243,22 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
throws
UserStoreException {
Claim[] userClaims = userClaimsCache.getValueFromCache(authorizedUser);
if(userClaims != null){
if (userClaims != null) {
return userClaims;
}else{
if(log.isDebugEnabled()){
} else {
if (log.isDebugEnabled()) {
log.debug("Cache miss for user claims. Username :" + authorizedUser);
}
userClaims = userStoreManager.getUserClaimValues(
authorizedUser, null);
userClaimsCache.addToCache(authorizedUser,userClaims);
userClaimsCache.addToCache(authorizedUser, userClaims);
return userClaims;
}
}
// Read the required claim configuration from identity.xml
/**
* Read the required claim configuration from identity.xml
*/
private void parseRequiredHeaderClaimUris(OMElement requiredClaimUrisElem) {
if (requiredClaimUrisElem == null) {
return;
@ -291,21 +278,22 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
/**
* Read the primary/secondary login configuration
* <OAuth>
* ....
* <LoginConfig>
* <UserIdLogin primary="true">
* <ClaimUri></ClaimUri>
* </UserIdLogin>
* <EmailLogin primary="false">
* <ClaimUri>http://wso2.org/claims/emailaddress</ClaimUri>
* </EmailLogin>
* </LoginConfig>
* .....
* </OAuth>
* ....
* <LoginConfig>
* <UserIdLogin primary="true">
* <ClaimUri></ClaimUri>
* </UserIdLogin>
* <EmailLogin primary="false">
* <ClaimUri>http://wso2.org/claims/emailaddress</ClaimUri>
* </EmailLogin>
* </LoginConfig>
* .....
* </OAuth>
*
* @param oauthConfigElem - The '<LoginConfig>' xml configuration element in the api-manager.xml
*/
private void parseLoginConfig(OMElement oauthConfigElem) {
OMElement loginConfigElem = oauthConfigElem.getFirstChildWithName(getQNameWithIdentityNS(LOGIN_CONFIG));
OMElement loginConfigElem = oauthConfigElem.getFirstChildWithName(getQNameWithIdentityNS(LOGIN_CONFIG));
if (loginConfigElem != null) {
if (log.isDebugEnabled()) {
log.debug("Login configuration is set ");
@ -313,7 +301,7 @@ public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
// Primary/Secondary supported login mechanisms
OMElement emailConfigElem = loginConfigElem.getFirstChildWithName(getQNameWithIdentityNS(EMAIL_LOGIN));
OMElement userIdConfigElem = loginConfigElem.getFirstChildWithName(getQNameWithIdentityNS(USERID_LOGIN));
OMElement userIdConfigElem = loginConfigElem.getFirstChildWithName(getQNameWithIdentityNS(USERID_LOGIN));
Map<String, String> emailConf = new HashMap<String, String>(2);
emailConf.put(PRIMARY_LOGIN,

Loading…
Cancel
Save