From 4c56d659255fc7b3f007873b68c900ad8263c346 Mon Sep 17 00:00:00 2001 From: warunalakshitha Date: Tue, 3 Oct 2017 12:35:33 +0530 Subject: [PATCH] Add constants to common class --- .../pom.xml | 2 +- .../pom.xml | 2 +- .../RemoteSessionManagementService.java | 14 +- .../RemoteSessionManagementServiceImpl.java | 4 + .../oauth/OAuthTokenValidator.java | 296 +++++++++--------- .../oauth/OAuthTokenValidatorStubFactory.java | 3 +- .../constants/RemoteSessionConstants.java | 17 + .../remote-session-extension/pom.xml | 2 +- .../pom.xml | 4 +- 9 files changed, 182 insertions(+), 162 deletions(-) diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/pom.xml b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/pom.xml index 88edfc0996..994afd9363 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/pom.xml +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.devicemgt-plugins remote-session-extension - 4.0.66-SNAPSHOT + 4.0.87-SNAPSHOT ../pom.xml diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/pom.xml b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/pom.xml index 659aac91f6..69224227b9 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/pom.xml +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.devicemgt-plugins remote-session-extension - 4.0.66-SNAPSHOT + 4.0.87-SNAPSHOT ../pom.xml diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementService.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementService.java index 53db138812..ce6f155d12 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementService.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementService.java @@ -28,18 +28,18 @@ import java.io.IOException; public interface RemoteSessionManagementService { /** - * Initialize session based on web socket request .this method use by the device to connect + * Initialize session based on web socket request .This method is used by the device to connect * * @param session Web socket RemoteSession * @param deviceType Device Type * @param deviceId Device Id * @throws RemoteSessionManagementException throws when session has errors with accessing device resources */ - public void initializeSession(Session session, String deviceType, String deviceId) throws + void initializeSession(Session session, String deviceType, String deviceId) throws RemoteSessionManagementException; /** - * Initialize session based on web socket request . This method use by the device to connect + * Initialize session based on web socket request . This method is used by the device to connect * * @param session Web socket RemoteSession * @param deviceType Device Type @@ -47,7 +47,7 @@ public interface RemoteSessionManagementService { * @param operationId Operation Id that device needs to connec * @throws RemoteSessionManagementException throws when session has errors with accessing device resources */ - public void initializeSession(Session session, String deviceType, String deviceId, String operationId) throws + void initializeSession(Session session, String deviceType, String deviceId, String operationId) throws RemoteSessionManagementException; /** @@ -57,7 +57,7 @@ public interface RemoteSessionManagementService { * @param message Message needs to send to peer connection client * @throws RemoteSessionManagementException */ - public void sendMessageToPeer(Session session, String message) throws RemoteSessionManagementException; + void sendMessageToPeer(Session session, String message) throws RemoteSessionManagementException; /** * Send byte message to connected remote device or client @@ -66,13 +66,13 @@ public interface RemoteSessionManagementService { * @param message Message needs to send to peer connection * @throws RemoteSessionManagementException */ - public void sendMessageToPeer(Session session, byte[] message) throws RemoteSessionManagementException; + void sendMessageToPeer(Session session, byte[] message) throws RemoteSessionManagementException; /** * Close the session * * @param session Web socket RemoteSession */ - public void endSession(Session session,String closeReason); + void endSession(Session session, String closeReason); } diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java index 8c1a8a7ab3..61f8d1624a 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java @@ -47,6 +47,10 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +/** + * Class @{@link RemoteSessionManagementServiceImpl} is the implementation of @{@link RemoteSessionManagementService} + * which is used manage initial connection, sending messages to peer session, manage and close the session. + */ public class RemoteSessionManagementServiceImpl implements RemoteSessionManagementService { private static final Log log = LogFactory.getLog(RemoteSessionManagementServiceImpl.class); diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/authentication/oauth/OAuthTokenValidator.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/authentication/oauth/OAuthTokenValidator.java index 3eb6d0db28..352289cf23 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/authentication/oauth/OAuthTokenValidator.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/authentication/oauth/OAuthTokenValidator.java @@ -27,7 +27,6 @@ import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_ import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; - import java.rmi.RemoteException; import java.util.HashMap; import java.util.List; @@ -38,160 +37,161 @@ import java.util.Map; */ public class OAuthTokenValidator { - private static String cookie; - private GenericObjectPool stubs; - private static Log log = LogFactory.getLog(OAuthTokenValidator.class); - private static final String COOKIE_KEY_VALUE_SEPERATOR = "="; - private static final String COOKIE_KEYPAIR_SEPERATOR = ";"; - private static final String COOKIE = "cookie"; - private static final String TOKEN_TYPE = "bearer"; - private static final String TOKEN_IDENTIFIER = "websocketToken"; - private static final String QUERY_STRING_SEPERATOR = "&"; - private static final String QUERY_KEY_VALUE_SEPERATOR = "="; - private static final String QUERY_STRING = "queryString"; - private static OAuthTokenValidator oAuthTokenValidator; + private static String cookie; + private GenericObjectPool stubs; + private static Log log = LogFactory.getLog(OAuthTokenValidator.class); + private static OAuthTokenValidator oAuthTokenValidator; - public OAuthTokenValidator(Map globalProperties) { - this.stubs = new GenericObjectPool(new OAuthTokenValidatorStubFactory(globalProperties)); - } + public OAuthTokenValidator(Map globalProperties) { + this.stubs = new GenericObjectPool(new OAuthTokenValidatorStubFactory(globalProperties)); + } - /** - * This method gets a string accessToken and validates it - * @param webSocketConnectionProperties WebSocket connection information including http headers - * @return AuthenticationInfo with the validated results. - */ - public AuthenticationInfo validateToken(Map> webSocketConnectionProperties) { - String token = getTokenFromSession(webSocketConnectionProperties); - if (token == null) { - AuthenticationInfo authenticationInfo = new AuthenticationInfo(); - authenticationInfo.setAuthenticated(false); - return authenticationInfo; - } - OAuth2TokenValidationServiceStub tokenValidationServiceStub = null; - try { - Object stub = this.stubs.borrowObject(); - if (stub != null) { - tokenValidationServiceStub = (OAuth2TokenValidationServiceStub) stub; - if (cookie != null) { - tokenValidationServiceStub._getServiceClient().getOptions().setProperty( - HTTPConstants.COOKIE_STRING, cookie); - } - return getAuthenticationInfo(token, tokenValidationServiceStub); - } else { - log.warn("Stub initialization failed."); - } - } catch (RemoteException e) { - log.error("Error on connecting with the validation endpoint.", e); - } catch (Exception e) { - log.error("Error occurred in borrowing an validation stub from the pool.", e); + /** + * This method gets a string accessToken and validates it + * + * @param webSocketConnectionProperties WebSocket connection information including http headers + * @return AuthenticationInfo with the validated results. + */ + public AuthenticationInfo validateToken(Map> webSocketConnectionProperties) { + String token = getTokenFromSession(webSocketConnectionProperties); + if (token == null) { + AuthenticationInfo authenticationInfo = new AuthenticationInfo(); + authenticationInfo.setAuthenticated(false); + return authenticationInfo; + } + OAuth2TokenValidationServiceStub tokenValidationServiceStub = null; + try { + Object stub = this.stubs.borrowObject(); + if (stub != null) { + tokenValidationServiceStub = (OAuth2TokenValidationServiceStub) stub; + if (cookie != null) { + tokenValidationServiceStub._getServiceClient().getOptions().setProperty( + HTTPConstants.COOKIE_STRING, cookie); + } + return getAuthenticationInfo(token, tokenValidationServiceStub); + } else { + log.warn("Stub initialization failed."); + } + } catch (RemoteException e) { + log.error("Error on connecting with the validation endpoint.", e); + } catch (Exception e) { + log.error("Error occurred in borrowing an validation stub from the pool.", e); - } finally { - try { - if (tokenValidationServiceStub != null) { - this.stubs.returnObject(tokenValidationServiceStub); - } - } catch (Exception e) { - log.warn("Error occurred while returning the object back to the oauth token validation service " + - "stub pool.", e); - } - } - AuthenticationInfo authenticationInfo = new AuthenticationInfo(); - authenticationInfo.setAuthenticated(false); - return authenticationInfo; - } + } finally { + try { + if (tokenValidationServiceStub != null) { + this.stubs.returnObject(tokenValidationServiceStub); + } + } catch (Exception e) { + log.warn("Error occurred while returning the object back to the oauth token validation service " + + "stub pool.", e); + } + } + AuthenticationInfo authenticationInfo = new AuthenticationInfo(); + authenticationInfo.setAuthenticated(false); + return authenticationInfo; + } - /** - * This creates an AuthenticationInfo object that is used for authorization. This method will validate the token - * and - * sets the required parameters to the object. - * - * @param token that needs to be validated. - * @param tokenValidationServiceStub stub that is used to call the external service. - * @return AuthenticationInfo This contains the information related to authenticated client. - * @throws RemoteException that triggers when failing to call the external service.. - */ - private AuthenticationInfo getAuthenticationInfo(String token, - OAuth2TokenValidationServiceStub tokenValidationServiceStub) - throws RemoteException { - AuthenticationInfo authenticationInfo = new AuthenticationInfo(); - OAuth2TokenValidationRequestDTO validationRequest = new OAuth2TokenValidationRequestDTO(); - OAuth2TokenValidationRequestDTO_OAuth2AccessToken accessToken = - new OAuth2TokenValidationRequestDTO_OAuth2AccessToken(); - accessToken.setTokenType(TOKEN_TYPE); - accessToken.setIdentifier(token); - validationRequest.setAccessToken(accessToken); - boolean authenticated; - OAuth2TokenValidationResponseDTO tokenValidationResponse; - tokenValidationResponse = tokenValidationServiceStub.validate(validationRequest); - if (tokenValidationResponse == null) { - authenticationInfo.setAuthenticated(false); - return authenticationInfo; - } - authenticated = tokenValidationResponse.getValid(); - if (authenticated) { - String authorizedUser = tokenValidationResponse.getAuthorizedUser(); - String username = MultitenantUtils.getTenantAwareUsername(authorizedUser); - String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser); - authenticationInfo.setUsername(username); - authenticationInfo.setTenantDomain(tenantDomain); - String scopes[] = tokenValidationResponse.getScope(); - if (scopes != null) { - Map properties = new HashMap<>(); - properties.put(RemoteSessionConstants.SCOPE_IDENTIFIER, scopes); - authenticationInfo.setProperties(properties); - } - } else { - if (log.isDebugEnabled()) { - log.debug("Token validation failed for token: " + token); - } - } - ServiceContext serviceContext = tokenValidationServiceStub._getServiceClient() - .getLastOperationContext().getServiceContext(); - cookie = (String) serviceContext.getProperty(HTTPConstants.COOKIE_STRING); - authenticationInfo.setAuthenticated(authenticated); - return authenticationInfo; - } + /** + * This creates an AuthenticationInfo object that is used for authorization. This method will validate the token + * and + * sets the required parameters to the object. + * + * @param token that needs to be validated. + * @param tokenValidationServiceStub stub that is used to call the external service. + * @return AuthenticationInfo This contains the information related to authenticated client. + * @throws RemoteException that triggers when failing to call the external service.. + */ + private AuthenticationInfo getAuthenticationInfo(String token, + OAuth2TokenValidationServiceStub tokenValidationServiceStub) + throws RemoteException { + AuthenticationInfo authenticationInfo = new AuthenticationInfo(); + OAuth2TokenValidationRequestDTO validationRequest = new OAuth2TokenValidationRequestDTO(); + OAuth2TokenValidationRequestDTO_OAuth2AccessToken accessToken = + new OAuth2TokenValidationRequestDTO_OAuth2AccessToken(); + accessToken.setTokenType(RemoteSessionConstants.OAuthTokenValidator.TOKEN_TYPE); + accessToken.setIdentifier(token); + validationRequest.setAccessToken(accessToken); + boolean authenticated; + OAuth2TokenValidationResponseDTO tokenValidationResponse; + tokenValidationResponse = tokenValidationServiceStub.validate(validationRequest); + if (tokenValidationResponse == null) { + authenticationInfo.setAuthenticated(false); + return authenticationInfo; + } + authenticated = tokenValidationResponse.getValid(); + if (authenticated) { + String authorizedUser = tokenValidationResponse.getAuthorizedUser(); + String username = MultitenantUtils.getTenantAwareUsername(authorizedUser); + String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser); + authenticationInfo.setUsername(username); + authenticationInfo.setTenantDomain(tenantDomain); + String scopes[] = tokenValidationResponse.getScope(); + if (scopes != null) { + Map properties = new HashMap<>(); + properties.put(RemoteSessionConstants.SCOPE_IDENTIFIER, scopes); + authenticationInfo.setProperties(properties); + } + } else { + if (log.isDebugEnabled()) { + log.debug("Token validation failed for token: " + token); + } + } + ServiceContext serviceContext = tokenValidationServiceStub._getServiceClient() + .getLastOperationContext().getServiceContext(); + cookie = (String) serviceContext.getProperty(HTTPConstants.COOKIE_STRING); + authenticationInfo.setAuthenticated(authenticated); + return authenticationInfo; + } - /** - * Retrieving the token from the http header - * @param webSocketConnectionProperties WebSocket connection information including http headers - * @return retrieved token - */ - private String getToken(Map> webSocketConnectionProperties) { - String cookieString = webSocketConnectionProperties.get(COOKIE).get(0); - String[] properties = cookieString.split(COOKIE_KEYPAIR_SEPERATOR); - String token; - for (String keyValuePair: properties) { - if(TOKEN_IDENTIFIER.equals((keyValuePair.split(COOKIE_KEY_VALUE_SEPERATOR)[0]).trim())){ - token = (keyValuePair.split(COOKIE_KEY_VALUE_SEPERATOR)[1]).trim(); - return token; + /** + * Retrieving the token from the http header + * + * @param webSocketConnectionProperties WebSocket connection information including http headers + * @return retrieved token + */ + private String getToken(Map> webSocketConnectionProperties) { + String cookieString = webSocketConnectionProperties.get(RemoteSessionConstants.OAuthTokenValidator.COOKIE) + .get(0); + String[] properties = cookieString.split(RemoteSessionConstants.OAuthTokenValidator.COOKIE_KEYPAIR_SEPERATOR); + String token; + for (String keyValuePair : properties) { + if (RemoteSessionConstants.OAuthTokenValidator.TOKEN_IDENTIFIER.equals((keyValuePair. + split(RemoteSessionConstants.OAuthTokenValidator.COOKIE_KEY_VALUE_SEPERATOR)[0]).trim())) { + token = (keyValuePair.split(RemoteSessionConstants.OAuthTokenValidator.COOKIE_KEY_VALUE_SEPERATOR) + [1]).trim(); + return token; } } - log.error("WebSocket token should be specified in cookie"); - return null; - } + log.error("WebSocket token should be specified in cookie"); + return null; + } - /** - * Retrieving the token from the http session - * @param webSocketConnectionProperties WebSocket connection information including http headers - * @return retrieved token - */ - private String getTokenFromSession(Map> webSocketConnectionProperties) { - String queryString = webSocketConnectionProperties.get(QUERY_STRING).get(0); - if (queryString != null) { - String[] allQueryParamPairs = queryString.split(QUERY_STRING_SEPERATOR); - for (String keyValuePair : allQueryParamPairs) { - String[] queryParamPair = keyValuePair.split(QUERY_KEY_VALUE_SEPERATOR); - if (queryParamPair.length != 2) { - log.warn("Invalid query string [" + queryString + "] passed in."); - break; - } - if (queryParamPair[0].equals(TOKEN_IDENTIFIER)) { - return queryParamPair[1]; - } - } - } - return null; - } + /** + * Retrieving the token from the http session + * + * @param webSocketConnectionProperties WebSocket connection information including http headers + * @return retrieved token + */ + private String getTokenFromSession(Map> webSocketConnectionProperties) { + String queryString = webSocketConnectionProperties.get(RemoteSessionConstants.OAuthTokenValidator + .QUERY_STRING).get(0); + if (queryString != null) { + String[] allQueryParamPairs = queryString.split(RemoteSessionConstants.OAuthTokenValidator + .QUERY_STRING_SEPERATOR); + for (String keyValuePair : allQueryParamPairs) { + String[] queryParamPair = keyValuePair.split(RemoteSessionConstants.OAuthTokenValidator + .QUERY_KEY_VALUE_SEPERATOR); + if (queryParamPair.length != 2) { + log.warn("Invalid query string [" + queryString + "] passed in."); + break; + } + if (queryParamPair[0].equals(RemoteSessionConstants.OAuthTokenValidator.TOKEN_IDENTIFIER)) { + return queryParamPair[1]; + } + } + } + return null; + } } diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/authentication/oauth/OAuthTokenValidatorStubFactory.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/authentication/oauth/OAuthTokenValidatorStubFactory.java index 9ee5a76936..15723a2c89 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/authentication/oauth/OAuthTokenValidatorStubFactory.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/authentication/oauth/OAuthTokenValidatorStubFactory.java @@ -143,8 +143,7 @@ public class OAuthTokenValidatorStubFactory extends BasePoolableObjectFactory { */ private EasySSLProtocolSocketFactory createProtocolSocketFactory() throws OAuthTokenValidationException { try { - EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory(); - return easySSLPSFactory; + return new EasySSLProtocolSocketFactory(); } catch (IOException e) { String errorMsg = "Failed to initiate EasySSLProtocolSocketFactory."; throw new OAuthTokenValidationException(errorMsg, e); diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/constants/RemoteSessionConstants.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/constants/RemoteSessionConstants.java index 07ebcd5082..2e899d7154 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/constants/RemoteSessionConstants.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/constants/RemoteSessionConstants.java @@ -44,4 +44,21 @@ public class RemoteSessionConstants { private RemoteSessionConstants() { } + /** + * OAuthTokenValidator specific constants + */ + public final class OAuthTokenValidator { + public static final String COOKIE_KEY_VALUE_SEPERATOR = "="; + public static final String COOKIE_KEYPAIR_SEPERATOR = ";"; + public static final String COOKIE = "cookie"; + public static final String TOKEN_TYPE = "bearer"; + public static final String TOKEN_IDENTIFIER = "websocketToken"; + public static final String QUERY_STRING_SEPERATOR = "&"; + public static final String QUERY_KEY_VALUE_SEPERATOR = "="; + public static final String QUERY_STRING = "queryString"; + + private OAuthTokenValidator() { + } + } + } diff --git a/components/extensions/remote-session-extension/pom.xml b/components/extensions/remote-session-extension/pom.xml index 44d6ca0876..ccecd1b6d3 100644 --- a/components/extensions/remote-session-extension/pom.xml +++ b/components/extensions/remote-session-extension/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.devicemgt-plugins extensions - 4.0.66-SNAPSHOT + 4.0.87-SNAPSHOT ../pom.xml diff --git a/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/pom.xml b/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/pom.xml index 09ee3efba8..c33b0ae79c 100644 --- a/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/pom.xml +++ b/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/pom.xml @@ -3,14 +3,14 @@ org.wso2.carbon.devicemgt-plugins extensions-feature - 4.0.66-SNAPSHOT + 4.0.87-SNAPSHOT ../pom.xml 4.0.0 org.wso2.carbon.device.mgt.remote.session.feature pom - 4.0.66-SNAPSHOT + 4.0.87-SNAPSHOT WSO2 Carbon - Remote Session Manager http://wso2.org This feature contains the core bundles required iot Remote Sessions