Search in sources :

Example 86 with Scope

use of org.wso2.carbon.apimgt.api.model.Scope in project carbon-apimgt by wso2.

the class SettingsMappingUtil method GetScopeList.

private List<String> GetScopeList() throws APIManagementException {
    String definition = null;
    try {
        definition = IOUtils.toString(RestApiUtil.class.getResourceAsStream("/devportal-api.yaml"), "UTF-8");
    } catch (IOException e) {
        log.error("Error while reading the swagger definition", e);
    }
    APIDefinition oasParser = OASParserUtil.getOASParser(definition);
    Set<Scope> scopeSet = oasParser.getScopes(definition);
    List<String> scopeList = new ArrayList<>();
    for (Scope entry : scopeSet) {
        scopeList.add(entry.getKey());
    }
    return scopeList;
}
Also used : Scope(org.wso2.carbon.apimgt.api.model.Scope) APIDefinition(org.wso2.carbon.apimgt.api.APIDefinition) ArrayList(java.util.ArrayList) IOException(java.io.IOException)

Example 87 with Scope

use of org.wso2.carbon.apimgt.api.model.Scope in project carbon-apimgt by wso2.

the class OAuthJwtAuthenticatorImpl method handleScopeValidation.

/**
 * Handle scope validation
 *
 * @param accessToken   JWT token
 * @param signedJWTInfo : Signed token info
 * @param message       : cxf Message
 */
private boolean handleScopeValidation(Message message, SignedJWTInfo signedJWTInfo, String accessToken) throws APIManagementException, ParseException {
    String maskedToken = message.get(RestApiConstants.MASKED_TOKEN).toString();
    OAuthTokenInfo oauthTokenInfo = new OAuthTokenInfo();
    oauthTokenInfo.setAccessToken(accessToken);
    oauthTokenInfo.setEndUserName(signedJWTInfo.getJwtClaimsSet().getSubject());
    String scopeClaim = signedJWTInfo.getJwtClaimsSet().getStringClaim(JwtTokenConstants.SCOPE);
    if (scopeClaim != null) {
        String orgId = RestApiUtil.resolveOrganization(message);
        String[] scopes = scopeClaim.split(JwtTokenConstants.SCOPE_DELIMITER);
        scopes = java.util.Arrays.stream(scopes).filter(s -> s.contains(orgId)).map(s -> s.replace(APIConstants.URN_CHOREO + orgId + ":", "")).toArray(size -> new String[size]);
        oauthTokenInfo.setScopes(scopes);
        if (validateScopes(message, oauthTokenInfo)) {
            // Add the user scopes list extracted from token to the cxf message
            message.getExchange().put(RestApiConstants.USER_REST_API_SCOPES, oauthTokenInfo.getScopes());
            // If scope validation successful then set tenant name and user name to current context
            String tenantDomain = MultitenantUtils.getTenantDomain(oauthTokenInfo.getEndUserName());
            int tenantId;
            PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
            RealmService realmService = (RealmService) carbonContext.getOSGiService(RealmService.class, null);
            try {
                String username = oauthTokenInfo.getEndUserName();
                if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
                    // when the username is an email in supertenant, it has at least 2 occurrences of '@'
                    long count = username.chars().filter(ch -> ch == '@').count();
                    // in the case of email, there will be more than one '@'
                    boolean isEmailUsernameEnabled = Boolean.parseBoolean(CarbonUtils.getServerConfiguration().getFirstProperty("EnableEmailUserName"));
                    if (isEmailUsernameEnabled || (username.endsWith(SUPER_TENANT_SUFFIX) && count <= 1)) {
                        username = MultitenantUtils.getTenantAwareUsername(username);
                    }
                }
                if (log.isDebugEnabled()) {
                    log.debug("username = " + username + "masked token " + maskedToken);
                }
                tenantId = realmService.getTenantManager().getTenantId(tenantDomain);
                carbonContext.setTenantDomain(tenantDomain);
                carbonContext.setTenantId(tenantId);
                carbonContext.setUsername(username);
                message.put(RestApiConstants.SUB_ORGANIZATION, orgId);
                if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
                    APIUtil.loadTenantConfigBlockingMode(tenantDomain);
                }
                return true;
            } catch (UserStoreException e) {
                log.error("Error while retrieving tenant id for tenant domain: " + tenantDomain, e);
            }
            log.debug("Scope validation success for the token " + maskedToken);
            return true;
        }
        log.error("scopes validation failed for the token" + maskedToken);
        return false;
    }
    log.error("scopes validation failed for the token" + maskedToken);
    return false;
}
Also used : MultitenantConstants(org.wso2.carbon.utils.multitenancy.MultitenantConstants) UserStoreException(org.wso2.carbon.user.api.UserStoreException) URL(java.net.URL) Date(java.util.Date) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) AbstractOAuthAuthenticator(org.wso2.carbon.apimgt.rest.api.util.authenticators.AbstractOAuthAuthenticator) MethodStats(org.wso2.carbon.apimgt.rest.api.util.MethodStats) PrivilegedCarbonContext(org.wso2.carbon.context.PrivilegedCarbonContext) StringUtils(org.apache.commons.lang3.StringUtils) RealmService(org.wso2.carbon.user.core.service.RealmService) APIConstants(org.wso2.carbon.apimgt.impl.APIConstants) CarbonUtils(org.wso2.carbon.utils.CarbonUtils) RestApiConstants(org.wso2.carbon.apimgt.rest.api.common.RestApiConstants) SignedJWTInfo(org.wso2.carbon.apimgt.impl.jwt.SignedJWTInfo) Map(java.util.Map) ParseException(java.text.ParseException) RESTAPICacheConfiguration(org.wso2.carbon.apimgt.impl.RESTAPICacheConfiguration) DateUtils(com.nimbusds.jwt.util.DateUtils) MalformedURLException(java.net.MalformedURLException) Message(org.apache.cxf.message.Message) JwtTokenConstants(org.wso2.carbon.apimgt.impl.APIConstants.JwtTokenConstants) APIUtil(org.wso2.carbon.apimgt.impl.utils.APIUtil) APIMConfigUtil(org.wso2.carbon.apimgt.rest.api.common.APIMConfigUtil) TokenIssuerDto(org.wso2.carbon.apimgt.common.gateway.dto.TokenIssuerDto) RestApiUtil(org.wso2.carbon.apimgt.rest.api.util.utils.RestApiUtil) SignedJWT(com.nimbusds.jwt.SignedJWT) JWTValidationInfo(org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo) List(java.util.List) JWTValidator(org.wso2.carbon.apimgt.impl.jwt.JWTValidator) MultitenantUtils(org.wso2.carbon.utils.multitenancy.MultitenantUtils) APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) OAuthTokenInfo(org.wso2.carbon.apimgt.api.OAuthTokenInfo) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) APIMConfigUtil.getRestApiJWTAuthAudiences(org.wso2.carbon.apimgt.rest.api.common.APIMConfigUtil.getRestApiJWTAuthAudiences) RealmService(org.wso2.carbon.user.core.service.RealmService) UserStoreException(org.wso2.carbon.user.api.UserStoreException) OAuthTokenInfo(org.wso2.carbon.apimgt.api.OAuthTokenInfo) PrivilegedCarbonContext(org.wso2.carbon.context.PrivilegedCarbonContext)

Example 88 with Scope

use of org.wso2.carbon.apimgt.api.model.Scope in project carbon-apimgt by wso2.

the class OAuthOpaqueAuthenticatorImpl method authenticate.

/**
 * @param message cxf message to be authenticated
 * @return true if authentication was successful else false
 * @throws APIManagementException when error in authentication process
 */
@Override
public boolean authenticate(Message message) throws APIManagementException {
    boolean retrievedFromInvalidTokenCache = false;
    boolean retrievedFromTokenCache = false;
    String accessToken = RestApiUtil.extractOAuthAccessTokenFromMessage(message, RestApiConstants.REGEX_BEARER_PATTERN, RestApiConstants.AUTH_HEADER_NAME);
    OAuthTokenInfo tokenInfo = null;
    RESTAPICacheConfiguration cacheConfiguration = APIUtil.getRESTAPICacheConfig();
    // validate the token from cache if it is enabled
    if (cacheConfiguration.isTokenCacheEnabled()) {
        tokenInfo = (OAuthTokenInfo) getRESTAPITokenCache().get(accessToken);
        if (tokenInfo != null) {
            if (isAccessTokenExpired(tokenInfo)) {
                tokenInfo.setTokenValid(false);
                // remove the token from token cache and put the token into invalid token cache
                // when the access token is expired
                getRESTAPIInvalidTokenCache().put(accessToken, tokenInfo);
                getRESTAPITokenCache().remove(accessToken);
                log.error(RestApiConstants.ERROR_TOKEN_EXPIRED);
                return false;
            } else {
                retrievedFromTokenCache = true;
            }
        } else {
            // if the token doesn't exist in the valid token cache, then check it in the invalid token cache
            tokenInfo = (OAuthTokenInfo) getRESTAPIInvalidTokenCache().get(accessToken);
            if (tokenInfo != null) {
                retrievedFromInvalidTokenCache = true;
            }
        }
    }
    // if the tokenInfo is null, then only retrieve the token information from the database
    try {
        if (tokenInfo == null) {
            tokenInfo = getTokenMetaData(accessToken);
        }
    } catch (APIManagementException e) {
        log.error("Error while retrieving token information for token: " + accessToken, e);
    }
    // if we got valid access token we will proceed with next
    if (tokenInfo != null && tokenInfo.isTokenValid()) {
        if (cacheConfiguration.isTokenCacheEnabled() && !retrievedFromTokenCache) {
            // put the token info into token cache
            getRESTAPITokenCache().put(accessToken, tokenInfo);
        }
        // If access token is valid then we will perform scope check for given resource.
        if (validateScopes(message, tokenInfo)) {
            // Add the user scopes list extracted from token to the cxf message
            message.getExchange().put(RestApiConstants.USER_REST_API_SCOPES, tokenInfo.getScopes());
            // If scope validation successful then set tenant name and user name to current context
            String tenantDomain = MultitenantUtils.getTenantDomain(tokenInfo.getEndUserName());
            int tenantId;
            PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
            RealmService realmService = (RealmService) carbonContext.getOSGiService(RealmService.class, null);
            try {
                String username = tokenInfo.getEndUserName();
                if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
                    // when the username is an email in supertenant, it has at least 2 occurrences of '@'
                    long count = username.chars().filter(ch -> ch == '@').count();
                    // in the case of email, there will be more than one '@'
                    boolean isEmailUsernameEnabled = Boolean.parseBoolean(CarbonUtils.getServerConfiguration().getFirstProperty("EnableEmailUserName"));
                    if (isEmailUsernameEnabled || (username.endsWith(SUPER_TENANT_SUFFIX) && count <= 1)) {
                        username = MultitenantUtils.getTenantAwareUsername(username);
                    }
                }
                if (log.isDebugEnabled()) {
                    log.debug("username = " + username);
                }
                tenantId = realmService.getTenantManager().getTenantId(tenantDomain);
                carbonContext.setTenantDomain(tenantDomain);
                carbonContext.setTenantId(tenantId);
                carbonContext.setUsername(username);
                message.put(RestApiConstants.SUB_ORGANIZATION, tenantDomain);
                if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
                    APIUtil.loadTenantConfigBlockingMode(tenantDomain);
                }
                return true;
            } catch (UserStoreException e) {
                log.error("Error while retrieving tenant id for tenant domain: " + tenantDomain, e);
            }
        } else {
            log.error(RestApiConstants.ERROR_SCOPE_VALIDATION_FAILED);
        }
    } else {
        log.error(RestApiConstants.ERROR_TOKEN_INVALID);
        if (cacheConfiguration.isTokenCacheEnabled() && !retrievedFromInvalidTokenCache) {
            getRESTAPIInvalidTokenCache().put(accessToken, tokenInfo);
        }
    }
    return false;
}
Also used : RESTAPICacheConfiguration(org.wso2.carbon.apimgt.impl.RESTAPICacheConfiguration) MultitenantConstants(org.wso2.carbon.utils.multitenancy.MultitenantConstants) Message(org.apache.cxf.message.Message) APIUtil(org.wso2.carbon.apimgt.impl.utils.APIUtil) UserStoreException(org.wso2.carbon.user.api.UserStoreException) OAuth2TokenValidationRequestDTO(org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationRequestDTO) AbstractOAuthAuthenticator(org.wso2.carbon.apimgt.rest.api.util.authenticators.AbstractOAuthAuthenticator) MethodStats(org.wso2.carbon.apimgt.rest.api.util.MethodStats) RestApiUtil(org.wso2.carbon.apimgt.rest.api.util.utils.RestApiUtil) PrivilegedCarbonContext(org.wso2.carbon.context.PrivilegedCarbonContext) RealmService(org.wso2.carbon.user.core.service.RealmService) APIConstants(org.wso2.carbon.apimgt.impl.APIConstants) APIKeyValidationInfoDTO(org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO) OAuth2TokenValidationService(org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService) OAuth2ClientApplicationDTO(org.wso2.carbon.identity.oauth2.dto.OAuth2ClientApplicationDTO) CarbonUtils(org.wso2.carbon.utils.CarbonUtils) MultitenantUtils(org.wso2.carbon.utils.multitenancy.MultitenantUtils) RestApiConstants(org.wso2.carbon.apimgt.rest.api.common.RestApiConstants) APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) OAuthTokenInfo(org.wso2.carbon.apimgt.api.OAuthTokenInfo) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) ServiceReferenceHolder(org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder) OAuth2TokenValidationResponseDTO(org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationResponseDTO) APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) RealmService(org.wso2.carbon.user.core.service.RealmService) UserStoreException(org.wso2.carbon.user.api.UserStoreException) OAuthTokenInfo(org.wso2.carbon.apimgt.api.OAuthTokenInfo) RESTAPICacheConfiguration(org.wso2.carbon.apimgt.impl.RESTAPICacheConfiguration) PrivilegedCarbonContext(org.wso2.carbon.context.PrivilegedCarbonContext)

Example 89 with Scope

use of org.wso2.carbon.apimgt.api.model.Scope in project carbon-apimgt by wso2.

the class SubscriberRegistrationInterceptor method handleMessage.

/**
 * Handles the incoming message after post authentication. Only used in Store REST API, to register a newly
 * signed up store user who hasn't logged in to Store for the first time either via REST API or Store UI.
 * This method will register the user as a subscriber
 * (register in AM_SUBSCRIBER table, add the default application for subscriber etc.).
 *
 * @param message cxf message
 */
@Override
@MethodStats
public void handleMessage(Message message) {
    String username = RestApiCommonUtil.getLoggedInUsername();
    // by-passes the interceptor if user is an annonymous user
    if (username.equalsIgnoreCase(APIConstants.WSO2_ANONYMOUS_USER)) {
        return;
    }
    // checking if the subscriber exists in the subscriber cache
    Cache<String, Subscriber> subscriberCache = Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER).getCache(APIConstants.API_SUBSCRIBER_CACHE);
    if (subscriberCache.get(username) != null) {
        return;
    }
    // check the existence in the database
    String groupId = RestApiUtil.getLoggedInUserGroupId();
    String tenantDomain = RestApiCommonUtil.getLoggedInUserTenantDomain();
    try {
        // takes a consumer object using the user set in thread local carbon context
        APIConsumer apiConsumer = RestApiCommonUtil.getLoggedInUserConsumer();
        Subscriber subscriber = apiConsumer.getSubscriber(username);
        if (subscriber == null) {
            synchronized ((username + LOCK_POSTFIX).intern()) {
                subscriber = apiConsumer.getSubscriber(username);
                if (subscriber == null) {
                    message.getExchange().get(RestApiConstants.USER_REST_API_SCOPES);
                    if (!hasSubscribeScope(message)) {
                        // permission. It should be allowed.
                        if (logger.isDebugEnabled()) {
                            logger.debug("User " + username + " does not have subscribe scope " + "(" + APIM_SUBSCRIBE_SCOPE + ")");
                        }
                        return;
                    }
                    if (!APIConstants.SUPER_TENANT_DOMAIN.equalsIgnoreCase(tenantDomain)) {
                        loadTenantRegistry();
                    }
                    apiConsumer.addSubscriber(username, groupId);
                    // The subscriber object added here is not a complete subscriber object. It will only contain
                    // username
                    subscriberCache.put(username, new Subscriber(username));
                    if (logger.isDebugEnabled()) {
                        logger.debug("Subscriber " + username + " added to AM_SUBSCRIBER database");
                    }
                }
            }
        } else {
            subscriberCache.put(username, subscriber);
        }
    } catch (APIManagementException e) {
        RestApiUtil.handleInternalServerError("Unable to add the subscriber " + username, e, logger);
    }
}
Also used : APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) Subscriber(org.wso2.carbon.apimgt.api.model.Subscriber) APIConsumer(org.wso2.carbon.apimgt.api.APIConsumer) MethodStats(org.wso2.carbon.apimgt.rest.api.util.MethodStats)

Example 90 with Scope

use of org.wso2.carbon.apimgt.api.model.Scope in project carbon-apimgt by wso2.

the class BasicAuthenticationInterceptor method validateUserRolesWithRESTAPIScopes.

/**
 * This method validates the user roles against the roles of the REST API scopes defined for the current resource.
 *
 * @param resourceScopeList Scope list of the current resource
 * @param restAPIScopes     RESTAPIScopes mapping for the current tenant
 * @param userRoles         Role list for the user
 * @param username          Username
 * @param path              Path Info
 * @param verb              HTTP Request Method
 * @param inMessage         cxf Message to set the matched user scopes for the resource
 * @return whether user role validation against REST API scope roles is success or not.
 */
private boolean validateUserRolesWithRESTAPIScopes(List<Scope> resourceScopeList, Map<String, String> restAPIScopes, String[] userRoles, String username, String path, String verb, Message inMessage) {
    // Holds the REST API scope list which the user will get successfully validated against with
    List<Scope> validatedUserScopes = new ArrayList<>();
    // iterate the non empty scope list of the URITemplate of the invoking resource
    for (Scope scope : resourceScopeList) {
        // get the configured roles list string of the requested resource
        String resourceRolesString = restAPIScopes.get(scope.getKey());
        if (StringUtils.isNotBlank(resourceRolesString)) {
            // split role list string read using comma separator
            List<String> resourceRoleList = Arrays.asList(resourceRolesString.split("\\s*,\\s*"));
            // check if the roles related to the API resource contains any of the role of the user
            for (String role : userRoles) {
                if (resourceRoleList.contains(role)) {
                    // Role validation is success. Add the current scope to the validated user scope list and
                    // skip role check iteration of current scope and move to next resource scope.
                    validatedUserScopes.add(scope);
                    if (log.isDebugEnabled()) {
                        log.debug("Basic Authentication: role validation successful for user: " + username + " with scope: " + scope.getKey() + " for resource path: " + path + " and verb " + verb);
                        log.debug("Added scope: " + scope.getKey() + " to validated user scope list");
                    }
                    break;
                }
            }
        } else {
            // No role for the requested resource scope. Add it to the validated user scope list.
            validatedUserScopes.add(scope);
            if (log.isDebugEnabled()) {
                log.debug("Role validation skipped. No REST API scope to role mapping defined for resource scope: " + scope.getKey() + " Treated as anonymous scope.");
            }
        }
    }
    List<String> scopes = new ArrayList<>();
    validatedUserScopes.forEach(scope -> scopes.add(scope.getKey()));
    // Add the validated user scope list to the cxf message
    inMessage.getExchange().put(RestApiConstants.USER_REST_API_SCOPES, scopes.toArray(new String[0]));
    if (!validatedUserScopes.isEmpty()) {
        if (log.isDebugEnabled()) {
            log.debug("Successfully validated REST API Scopes for the user " + username);
        }
        return true;
    }
    // none of the resource scopes were matched against the user role set
    log.error("Insufficient privileges. Role validation failed for user: " + username + " to access resource path: " + path + " and verb " + verb);
    return false;
}
Also used : Scope(org.wso2.carbon.apimgt.api.model.Scope) ArrayList(java.util.ArrayList)

Aggregations

Scope (org.wso2.carbon.apimgt.api.model.Scope)97 HashMap (java.util.HashMap)76 ArrayList (java.util.ArrayList)58 APIManagementException (org.wso2.carbon.apimgt.api.APIManagementException)50 Scope (org.wso2.carbon.apimgt.core.models.Scope)41 Map (java.util.Map)39 URITemplate (org.wso2.carbon.apimgt.api.model.URITemplate)39 LinkedHashSet (java.util.LinkedHashSet)32 LinkedHashMap (java.util.LinkedHashMap)29 HashSet (java.util.HashSet)26 RestVariable (org.wso2.carbon.bpmn.rest.engine.variable.RestVariable)25 List (java.util.List)24 Test (org.testng.annotations.Test)23 JSONObject (org.json.simple.JSONObject)22 APIManagementException (org.wso2.carbon.apimgt.core.exception.APIManagementException)19 PreparedStatement (java.sql.PreparedStatement)17 APIIdentifier (org.wso2.carbon.apimgt.api.model.APIIdentifier)17 SQLException (java.sql.SQLException)16 Gson (com.google.gson.Gson)15 Connection (java.sql.Connection)15