Merge pull request #416 from ayyoob/IoTS-1.0.0

refactored device verification
revert-dabc3590
Ruwan 8 years ago committed by GitHub
commit 1ff609d819

@ -25,13 +25,10 @@ import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Extension; import io.swagger.annotations.Extension;
import io.swagger.annotations.Tag; import io.swagger.annotations.Tag;
import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.DeviceType;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.Feature;
import javax.ws.rs.*; import javax.ws.rs.*;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
@DeviceType(value = "android_sense")
@SwaggerDefinition( @SwaggerDefinition(
info = @Info( info = @Info(
version = "1.0.0", version = "1.0.0",
@ -57,7 +54,6 @@ public interface AndroidSenseService {
*/ */
@Path("device/{deviceId}/words") @Path("device/{deviceId}/words")
@POST @POST
@Feature(code = "keywords", name = "Add Keywords", description = "Send keywords to the device")
@Scope(key = "device:android-sense:enroll", name = "", description = "") @Scope(key = "device:android-sense:enroll", name = "", description = "")
Response sendKeyWords(@PathParam("deviceId") String deviceId, @QueryParam("keywords") String keywords); Response sendKeyWords(@PathParam("deviceId") String deviceId, @QueryParam("keywords") String keywords);
@ -69,13 +65,11 @@ public interface AndroidSenseService {
*/ */
@Path("device/{deviceId}/words/threshold") @Path("device/{deviceId}/words/threshold")
@POST @POST
@Feature(code = "threshold", name = "Add a Threshold", description = "Set a threshold for word in the device")
@Scope(key = "device:android-sense:enroll", name = "", description = "") @Scope(key = "device:android-sense:enroll", name = "", description = "")
Response sendThreshold(@PathParam("deviceId") String deviceId, @QueryParam("threshold") String threshold); Response sendThreshold(@PathParam("deviceId") String deviceId, @QueryParam("threshold") String threshold);
@Path("device/{deviceId}/words") @Path("device/{deviceId}/words")
@DELETE @DELETE
@Feature(code = "remove", name = "Remove Keywords", description = "Remove the keywords")
@Scope(key = "device:android-sense:enroll", name = "", description = "") @Scope(key = "device:android-sense:enroll", name = "", description = "")
Response removeKeyWords(@PathParam("deviceId") String deviceId, @QueryParam("words") String words); Response removeKeyWords(@PathParam("deviceId") String deviceId, @QueryParam("words") String words);

@ -24,24 +24,11 @@ function onRequest(context) {
var constants = require("/app/modules/constants.js"); var constants = require("/app/modules/constants.js");
var websocketEndpoint = devicemgtProps["wssURL"].replace("https", "wss"); var websocketEndpoint = devicemgtProps["wssURL"].replace("https", "wss");
var jwtService = carbonServer.osgiService( var tokenPair = session.get(constants["TOKEN_PAIR"]);
'org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService'); if (tokenPair) {
var jwtClient = jwtService.getJWTClient(); var token = parse(tokenPair)["accessToken"];
var encodedClientKeys = session.get(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"]); websocketEndpoint = websocketEndpoint + "/secured-websocket/org.wso2.iot.android.sense/1.0.0?" +
if (encodedClientKeys) { "token="+ token +"&deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type;
var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"]; }
var resp = tokenUtil.decode(encodedClientKeys).split(":");
var deviceParam = "{\"scope\":\"stats\",\"deviceIdentifiers\":[{\"id\":\"" + device.deviceIdentifier
+ "\", \"type\":\"" + device.type + "\"}]}";
var encodedScope = tokenUtil.encode(deviceParam);
var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default",
{"device": encodedScope});
var token = "";
if (tokenPair) {
token = tokenPair.accessToken;
}
websocketEndpoint = websocketEndpoint + "/secured-outputui/org.wso2.iot.android.sense/1.0.0?" +
"token="+ token +"&deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type;
}
return {"device": device, "websocketEndpoint": websocketEndpoint}; return {"device": device, "websocketEndpoint": websocketEndpoint};
} }

@ -25,8 +25,6 @@ import io.swagger.annotations.Extension;
import io.swagger.annotations.Tag; import io.swagger.annotations.Tag;
import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.DeviceType;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.Feature;
import javax.ws.rs.*; import javax.ws.rs.*;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
@ -46,12 +44,10 @@ import javax.ws.rs.core.Response;
@Tag(name = "arduino", description = "") @Tag(name = "arduino", description = "")
} }
) )
@DeviceType(value = "arduino")
public interface ArduinoService { public interface ArduinoService {
@Path("device/{deviceId}/bulb") @Path("device/{deviceId}/bulb")
@POST @POST
@Feature(code = "bulb", name = "Control Bulb", description = "Control Bulb on Arduino Uno")
@Scope(key = "device:arduino:enroll", name = "", description = "") @Scope(key = "device:arduino:enroll", name = "", description = "")
Response switchBulb(@PathParam("deviceId") String deviceId, @QueryParam("state") String state); Response switchBulb(@PathParam("deviceId") String deviceId, @QueryParam("state") String state);

@ -229,7 +229,7 @@ public class ArduinoServiceImpl implements ArduinoService {
ArduinoConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true); ArduinoConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true);
} }
JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient(); JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient();
String scopes = "arduino_device cdmf/" + ArduinoConstants.DEVICE_TYPE + "/" + deviceId; String scopes = " device_" + deviceId;
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(), AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(),
apiApplicationKey.getConsumerSecret(), owner, scopes); apiApplicationKey.getConsumerSecret(), owner, scopes);
//create token //create token

@ -18,30 +18,17 @@
function onRequest(context) { function onRequest(context) {
var log = new Log("stats.js"); var log = new Log("stats.js");
var carbonServer = require("carbon").server;
var device = context.unit.params.device; var device = context.unit.params.device;
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"]; var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var constants = require("/app/modules/constants.js"); var constants = require("/app/modules/constants.js");
var websocketEndpoint = devicemgtProps["wssURL"].replace("https", "wss"); var websocketEndpoint = devicemgtProps["wssURL"].replace("https", "wss");
var jwtService = carbonServer.osgiService( var tokenPair = session.get(constants["TOKEN_PAIR"]);
'org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService'); if (tokenPair) {
var jwtClient = jwtService.getJWTClient(); var token = parse(tokenPair)["accessToken"];
var encodedClientKeys = session.get(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"]); websocketEndpoint = websocketEndpoint + "/secured-websocket/org.wso2.iot.devices.temperature/1.0.0?" +
if (encodedClientKeys) { "token="+ token +"&deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type;
var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"]; }
var resp = tokenUtil.decode(encodedClientKeys).split(":");
var deviceParam = "{\"scope\":\"stats\",\"deviceIdentifiers\":[{\"id\":\"" + device.deviceIdentifier
+ "\", \"type\":\"" + device.type + "\"}]}";
var encodedScope = tokenUtil.encode(deviceParam);
var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default",
{"device": encodedScope});
var token = "";
if (tokenPair) {
token = tokenPair.accessToken;
}
websocketEndpoint = websocketEndpoint + "/secured-outputui/org.wso2.iot.devices.temperature/1.0.0?" +
"token="+ token +"&deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type;
}
return {"device": device, "websocketEndpoint": websocketEndpoint}; return {"device": device, "websocketEndpoint": websocketEndpoint};
} }

@ -24,8 +24,6 @@ import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Extension; import io.swagger.annotations.Extension;
import io.swagger.annotations.Tag; import io.swagger.annotations.Tag;
import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.DeviceType;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.Feature;
import javax.ws.rs.*; import javax.ws.rs.*;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
@ -46,12 +44,10 @@ import javax.ws.rs.core.Response;
@Tag(name = "raspberrypi", description = "") @Tag(name = "raspberrypi", description = "")
} }
) )
@DeviceType(value = "raspberrypi")
public interface RaspberryPiService { public interface RaspberryPiService {
@Path("device/{deviceId}/bulb") @Path("device/{deviceId}/bulb")
@POST @POST
@Feature(code = "bulb", name = "Bulb On / Off", description = "Switch on/off Raspberry Pi agent's bulb. (On / Off)")
@Scope(key = "device:raspberrypi:enroll", name = "", description = "") @Scope(key = "device:raspberrypi:enroll", name = "", description = "")
Response switchBulb(@PathParam("deviceId") String deviceId, @QueryParam("state") String state); Response switchBulb(@PathParam("deviceId") String deviceId, @QueryParam("state") String state);

@ -213,7 +213,7 @@ public class RaspberryPiServiceImpl implements RaspberryPiService {
RaspberrypiConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true); RaspberrypiConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true);
} }
JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient(); JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient();
String scopes = "cdmf/" + RaspberrypiConstants.DEVICE_TYPE + "/" + deviceId; String scopes = " device_" + deviceId;
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(), AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(),
apiApplicationKey.getConsumerSecret(), owner, scopes); apiApplicationKey.getConsumerSecret(), owner, scopes);
//create token //create token

@ -18,30 +18,17 @@
function onRequest(context) { function onRequest(context) {
var log = new Log("stats.js"); var log = new Log("stats.js");
var carbonServer = require("carbon").server;
var device = context.unit.params.device; var device = context.unit.params.device;
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"]; var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var constants = require("/app/modules/constants.js"); var constants = require("/app/modules/constants.js");
var websocketEndpoint = devicemgtProps["wssURL"].replace("https", "wss"); var websocketEndpoint = devicemgtProps["wssURL"].replace("https", "wss");
var jwtService = carbonServer.osgiService( var tokenPair = session.get(constants["TOKEN_PAIR"]);
'org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService'); if (tokenPair) {
var jwtClient = jwtService.getJWTClient(); var token = parse(tokenPair)["accessToken"];
var encodedClientKeys = session.get(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"]); websocketEndpoint = websocketEndpoint + "/secured-websocket/org.wso2.iot.devices.temperature/1.0.0?" +
if (encodedClientKeys) { "token="+ token +"&deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type;
var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"]; }
var resp = tokenUtil.decode(encodedClientKeys).split(":");
var deviceParam = "{\"scope\":\"stats\",\"deviceIdentifiers\":[{\"id\":\"" + device.deviceIdentifier
+ "\", \"type\":\"" + device.type + "\"}]}";
var encodedScope = tokenUtil.encode(deviceParam);
var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default",
{"device": encodedScope});
var token = "";
if (tokenPair) {
token = tokenPair.accessToken;
}
websocketEndpoint = websocketEndpoint + "/secured-outputui/org.wso2.iot.devices.temperature/1.0.0?" +
"token="+ token +"&deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type;
}
return {"device": device, "websocketEndpoint": websocketEndpoint}; return {"device": device, "websocketEndpoint": websocketEndpoint};
} }

@ -24,8 +24,6 @@ import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Extension; import io.swagger.annotations.Extension;
import io.swagger.annotations.Tag; import io.swagger.annotations.Tag;
import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.DeviceType;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.Feature;
import javax.ws.rs.*; import javax.ws.rs.*;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
@ -52,7 +50,6 @@ import javax.ws.rs.core.Response;
@Tag(name = "virtual_firealarm", description = "") @Tag(name = "virtual_firealarm", description = "")
} }
) )
@DeviceType(value = "virtual_firealarm")
public interface VirtualFireAlarmService { public interface VirtualFireAlarmService {
/** /**
@ -67,7 +64,6 @@ public interface VirtualFireAlarmService {
@POST @POST
@Path("device/{deviceId}/buzz") @Path("device/{deviceId}/buzz")
@Scope(key = "device:firealarm:enroll", name = "", description = "") @Scope(key = "device:firealarm:enroll", name = "", description = "")
@Feature(code = "buzz", name = "Buzzer On / Off", description = "Switch on/off Virtual Fire Alarm Buzzer. (On / Off)")
Response switchBuzzer(@PathParam("deviceId") String deviceId, Response switchBuzzer(@PathParam("deviceId") String deviceId,
@FormParam("state") String state); @FormParam("state") String state);

@ -312,13 +312,10 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
VirtualFireAlarmConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true); VirtualFireAlarmConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true);
} }
JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient(); JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient();
String device = "{ \"scope\":\"mqtt-publisher mqtt-subscriber\", \"deviceIdentifiers\":[{\"id\":\""+deviceId+"\", " + String scopes = " device_" + deviceId;
"\"type\":\""+VirtualFireAlarmConstants.DEVICE_TYPE+"\"}]}";
Map<String, String> params = new HashMap<String, String>();
params.put("device", Base64.encodeBase64String(device.getBytes()));
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(), AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(),
apiApplicationKey.getConsumerSecret(), owner, apiApplicationKey.getConsumerSecret(), owner,
null, params); scopes);
String accessToken = accessTokenInfo.getAccessToken(); String accessToken = accessTokenInfo.getAccessToken();
String refreshToken = accessTokenInfo.getRefreshToken(); String refreshToken = accessTokenInfo.getRefreshToken();
XmppAccount newXmppAccount = new XmppAccount(); XmppAccount newXmppAccount = new XmppAccount();

@ -24,24 +24,13 @@ function onRequest(context) {
var constants = require("/app/modules/constants.js"); var constants = require("/app/modules/constants.js");
var websocketEndpoint = devicemgtProps["wssURL"].replace("https", "wss"); var websocketEndpoint = devicemgtProps["wssURL"].replace("https", "wss");
var jwtService = carbonServer.osgiService(
'org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService'); var tokenPair = session.get(constants["TOKEN_PAIR"]);
var jwtClient = jwtService.getJWTClient(); if (tokenPair) {
var encodedClientKeys = session.get(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"]); var token = parse(tokenPair)["accessToken"];
if (encodedClientKeys) { websocketEndpoint = websocketEndpoint + "/secured-websocket/org.wso2.iot.devices.temperature/1.0.0?" +
var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"]; "token=" + token + "&deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type;
var resp = tokenUtil.decode(encodedClientKeys).split(":"); }
var deviceParam = "{\"scope\":\"stats\",\"deviceIdentifiers\":[{\"id\":\"" + device.deviceIdentifier
+ "\", \"type\":\"" + device.type + "\"}]}";
var encodedScope = tokenUtil.encode(deviceParam);
var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default",
{"device": encodedScope});
var token = "";
if (tokenPair) {
token = tokenPair.accessToken;
}
websocketEndpoint = websocketEndpoint + "/secured-outputui/org.wso2.iot.devices.temperature/1.0.0?" +
"token=" + token + "&deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type;
}
return {"device": device, "websocketEndpoint": websocketEndpoint}; return {"device": device, "websocketEndpoint": websocketEndpoint};
} }

@ -58,6 +58,6 @@
</dependencies> </dependencies>
<build> <build>
<finalName>secured-outputui</finalName> <finalName>secured-websocket</finalName>
</build> </build>
</project> </project>

@ -79,6 +79,22 @@
<groupId>commons-pool.wso2</groupId> <groupId>commons-pool.wso2</groupId>
<artifactId>commons-pool</artifactId> <artifactId>commons-pool</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -147,9 +163,18 @@
org.wso2.carbon.identity.oauth2.stub, org.wso2.carbon.identity.oauth2.stub,
org.wso2.carbon.identity.oauth2.stub.dto, org.wso2.carbon.identity.oauth2.stub.dto,
org.wso2.carbon.user.api, org.wso2.carbon.user.api,
org.wso2.carbon.utils.multitenancy org.wso2.carbon.utils.multitenancy,
feign,
feign.auth,
feign.codec,
feign.gson,
javax.cache
</Import-Package> </Import-Package>
<DynamicImport-Package>*</DynamicImport-Package> <DynamicImport-Package>*</DynamicImport-Package>
<Embed-Dependency>
jsr311-api,
feign-jaxrs
</Embed-Dependency>
</instructions> </instructions>
</configuration> </configuration>
</plugin> </plugin>

@ -17,19 +17,52 @@
*/ */
package org.wso2.carbon.device.mgt.output.adapter.websocket.authorization; package org.wso2.carbon.device.mgt.output.adapter.websocket.authorization;
import feign.Feign;
import feign.FeignException;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import feign.jaxrs.JAXRSContract;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.AuthenticationInfo; import org.wso2.carbon.device.mgt.output.adapter.websocket.authentication.AuthenticationInfo;
import org.wso2.carbon.device.mgt.output.adapter.websocket.constants.WebsocketConstants; import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.OAuthRequestInterceptor;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.AuthorizationRequest;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto
.DeviceAccessAuthorizationAdminService;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.DeviceAuthorizationResult;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.DeviceIdentifier;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Properties;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Property;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketConfig;
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.WebSocketSessionRequest; import org.wso2.carbon.device.mgt.output.adapter.websocket.util.WebSocketSessionRequest;
import javax.websocket.Session; import javax.websocket.Session;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* This authorizer crossvalidates the request with device id and device type. * This authorizer crossvalidates the request with device id and device type.
*/ */
public class DeviceAuthorizer implements Authorizer { public class DeviceAuthorizer implements Authorizer {
private static final String STATS_SCOPE_IDENTIFIER = "stats";
private static final String DEVICE_MGT_SCOPE_IDENTIFIER = "device-mgt"; private static DeviceAccessAuthorizationAdminService deviceAccessAuthorizationAdminService;
private static final String CDMF_SERVER_BASE_CONTEXT = "/api/device-mgt/v1.0";
private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl";
private static final String STAT_PERMISSION = "statsPermission";
private static Log logger = LogFactory.getLog(DeviceAuthorizer.class);
private static List<String> statPermissions;
public DeviceAuthorizer() {
Properties properties =
WebsocketConfig.getInstance().getWebsocketValidationConfigs().getAuthorizer().getProperties();
statPermissions = getPermissions(properties);
deviceAccessAuthorizationAdminService = Feign.builder()
.requestInterceptor(new OAuthRequestInterceptor())
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(DeviceAccessAuthorizationAdminService.class, getDeviceMgtServerUrl(properties)
+ CDMF_SERVER_BASE_CONTEXT);
}
@Override @Override
public boolean isAuthorized(AuthenticationInfo authenticationInfo, Session session, String stream) { public boolean isAuthorized(AuthenticationInfo authenticationInfo, Session session, String stream) {
@ -37,19 +70,59 @@ public class DeviceAuthorizer implements Authorizer {
Map<String, String> queryParams = webSocketSessionRequest.getQueryParamValuePairs(); Map<String, String> queryParams = webSocketSessionRequest.getQueryParamValuePairs();
String deviceId = queryParams.get("deviceId"); String deviceId = queryParams.get("deviceId");
String deviceType = queryParams.get("deviceType"); String deviceType = queryParams.get("deviceType");
Object scopeObject = authenticationInfo.getProperties().get(WebsocketConstants.SCOPE_IDENTIFIER);
if (deviceId != null && !deviceId.isEmpty() && deviceType != null && !deviceType.isEmpty()) {
if (deviceId != null && !deviceId.isEmpty() && deviceType != null && !deviceType.isEmpty()
&& scopeObject != null) { AuthorizationRequest authorizationRequest = new AuthorizationRequest();
String scopes[] = (String[]) scopeObject; authorizationRequest.setTenantDomain(authenticationInfo.getTenantDomain());
String requiredScope = DEVICE_MGT_SCOPE_IDENTIFIER + ":" + deviceType + ":" + deviceId + ":" if (statPermissions != null && !statPermissions.isEmpty()) {
+ STATS_SCOPE_IDENTIFIER; authorizationRequest.setPermissions(statPermissions);
for (String scope : scopes) { }
if (requiredScope.equals(scope)) { authorizationRequest.setUsername(authenticationInfo.getUsername());
return true; DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(deviceType);
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>();
deviceIdentifiers.add(deviceIdentifier);
authorizationRequest.setDeviceIdentifiers(deviceIdentifiers);
try {
DeviceAuthorizationResult deviceAuthorizationResult =
deviceAccessAuthorizationAdminService.isAuthorized(authorizationRequest);
List<DeviceIdentifier> devices = deviceAuthorizationResult.getAuthorizedDevices();
if (devices != null && devices.size() > 0) {
DeviceIdentifier authorizedDevice = devices.get(0);
if (authorizedDevice.getId().equals(deviceId) && authorizedDevice.getType().equals(deviceType)) {
return true;
}
} }
} catch (FeignException e) {
logger.error(e.getMessage(), e);
} }
} }
return false; return false;
} }
private String getDeviceMgtServerUrl(Properties properties) {
String deviceMgtServerUrl = null;
for (Property property : properties.getProperty()) {
if (property.getName().equals(DEVICE_MGT_SERVER_URL)) {
deviceMgtServerUrl = property.getValue();
break;
}
}
if (deviceMgtServerUrl == null || deviceMgtServerUrl.isEmpty()) {
logger.error("deviceMgtServerUrl can't be empty ");
}
return deviceMgtServerUrl;
}
private List<String> getPermissions(Properties properties) {
List<String> permission = new ArrayList<>();
for (Property property : properties.getProperty()) {
if (property.getName().equals(STAT_PERMISSION)) {
permission.add(property.getValue());
}
}
return permission;
}
} }

@ -0,0 +1,178 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.output.adapter.websocket.authorization.client;
import feign.Feign;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.auth.BasicAuthRequestInterceptor;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import feign.jaxrs.JAXRSContract;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.AccessTokenInfo;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.ApiApplicationKey;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.ApiApplicationRegistrationService;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.ApiRegistrationProfile;
import org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.client.dto.TokenIssuerService;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Properties;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.Property;
import org.wso2.carbon.device.mgt.output.adapter.websocket.config.WebsocketConfig;
/**
* This is a request interceptor to add oauth token header.
*/
public class OAuthRequestInterceptor implements RequestInterceptor {
private AccessTokenInfo tokenInfo;
private long refreshTimeOffset;
private static final String API_APPLICATION_REGISTRATION_CONTEXT = "/api-application-registration";
private static final String DEVICE_MANAGEMENT_SERVICE_TAG[] = {"device_management"};
private static final String APPLICATION_NAME = "websocket-app";
private static final String PASSWORD_GRANT_TYPE = "password";
private static final String REFRESH_GRANT_TYPE = "refresh_token";
private ApiApplicationRegistrationService apiApplicationRegistrationService;
private TokenIssuerService tokenIssuerService;
private static Log logger = LogFactory.getLog(OAuthRequestInterceptor.class);
private static final String CONNECTION_USERNAME = "username";
private static final String CONNECTION_PASSWORD = "password";
private static final String TOKEN_ENDPOINT = "tokenEndpoint";
private static final String TOKEN_REFRESH_TIME_OFFSET = "tokenRefreshTimeOffset";
private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl";
private static String username;
private static String password;
private static String tokenEndpoint;
private static String deviceMgtServerUrl;
/**
* Creates an interceptor that authenticates all requests.
*/
public OAuthRequestInterceptor() {
Properties properties =
WebsocketConfig.getInstance().getWebsocketValidationConfigs().getAuthorizer().getProperties();
deviceMgtServerUrl = getDeviceMgtServerUrl(properties);
refreshTimeOffset = getRefreshTimeOffset(properties);
username = getUsername(properties);
password = getPassword(properties);
tokenEndpoint = getTokenEndpoint(properties);
apiApplicationRegistrationService = Feign.builder().requestInterceptor(
new BasicAuthRequestInterceptor(username, password))
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(ApiApplicationRegistrationService.class,
deviceMgtServerUrl + API_APPLICATION_REGISTRATION_CONTEXT);
}
@Override
public void apply(RequestTemplate template) {
if (tokenInfo == null) {
//had to do on demand initialization due to start up error.
ApiRegistrationProfile apiRegistrationProfile = new ApiRegistrationProfile();
apiRegistrationProfile.setApplicationName(APPLICATION_NAME);
apiRegistrationProfile.setIsAllowedToAllDomains(false);
apiRegistrationProfile.setIsMappingAnExistingOAuthApp(false);
apiRegistrationProfile.setTags(DEVICE_MANAGEMENT_SERVICE_TAG);
ApiApplicationKey apiApplicationKey = apiApplicationRegistrationService.register(apiRegistrationProfile);
String consumerKey = apiApplicationKey.getConsumerKey();
String consumerSecret = apiApplicationKey.getConsumerSecret();
tokenIssuerService = Feign.builder().requestInterceptor(
new BasicAuthRequestInterceptor(consumerKey, consumerSecret))
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(TokenIssuerService.class, tokenEndpoint);
tokenInfo = tokenIssuerService.getToken(PASSWORD_GRANT_TYPE, username, password);
tokenInfo.setExpires_in(System.currentTimeMillis() + tokenInfo.getExpires_in());
}
if (System.currentTimeMillis() + refreshTimeOffset > tokenInfo.getExpires_in()) {
tokenInfo = tokenIssuerService.getToken(REFRESH_GRANT_TYPE, tokenInfo.getRefresh_token());
tokenInfo.setExpires_in(System.currentTimeMillis() + tokenInfo.getExpires_in());
}
String headerValue = "Bearer " + tokenInfo.getAccess_token();
template.header("Authorization", headerValue);
}
private String getUsername(Properties properties) {
String username = null;
for (Property property : properties.getProperty()) {
if (property.getName().equals(CONNECTION_USERNAME)) {
username = property.getValue();
break;
}
}
if (username == null || username.isEmpty()) {
logger.error("username can't be empty ");
}
return username;
}
private String getPassword(Properties properties) {
String password = null;
for (Property property : properties.getProperty()) {
if (property.getName().equals(CONNECTION_PASSWORD)) {
password = property.getValue();
break;
}
}
if (password == null || password.isEmpty()) {
logger.error("password can't be empty ");
}
return password;
}
private String getDeviceMgtServerUrl(Properties properties) {
String deviceMgtServerUrl = null;
for (Property property : properties.getProperty()) {
if (property.getName().equals(DEVICE_MGT_SERVER_URL)) {
deviceMgtServerUrl = property.getValue();
break;
}
}
if (deviceMgtServerUrl == null || deviceMgtServerUrl.isEmpty()) {
logger.error("deviceMgtServerUrl can't be empty ");
}
return deviceMgtServerUrl;
}
private String getTokenEndpoint(Properties properties) {
String tokenEndpoint = null;
for (Property property : properties.getProperty()) {
if (property.getName().equals(TOKEN_ENDPOINT)) {
tokenEndpoint = property.getValue();
break;
}
}
if (tokenEndpoint == null || tokenEndpoint.isEmpty()) {
logger.error("tokenEndpoint can't be empty ");
}
return tokenEndpoint;
}
private long getRefreshTimeOffset(Properties properties) {
long refreshTimeOffset = 0;
try {
for (Property property : properties.getProperty()) {
if (property.getName().equals(TOKEN_REFRESH_TIME_OFFSET)) {
refreshTimeOffset = Long.parseLong(property.getValue());
break;
}
}
} catch (NumberFormatException e) {
logger.error("refreshTimeOffset should be a number", e);
}
return refreshTimeOffset;
}
}

@ -0,0 +1,57 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.output.adapter.websocket.authorization.client.dto;
/**
* This hold access token info that returned from the api call
*/
public class AccessTokenInfo {
public String token_type;
public long expires_in;
public String refresh_token;
public String access_token;
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
public long getExpires_in() {
return expires_in;
}
public void setExpires_in(long expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
}

@ -0,0 +1,43 @@
/*
* 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.output.adapter.websocket.authorization.client.dto;
/**
* This holds api application consumer key and secret.
*/
public class ApiApplicationKey {
private String client_id;
private String client_secret;
public String getConsumerKey() {
return this.client_id;
}
public void setClient_id(String consumerKey) {
this.client_id = consumerKey;
}
public String getConsumerSecret() {
return this.client_secret;
}
public void setClient_secret(String consumerSecret) {
this.client_secret = consumerSecret;
}
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.output.adapter.websocket.authorization.client.dto;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* This is the application registration service that exposed for apimApplicationRegistration
*/
@Path("/register")
public interface ApiApplicationRegistrationService {
/**
* This method is used to register api application
*
* @param registrationProfile contains the necessary attributes that are needed in order to register an app.
*/
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
ApiApplicationKey register(ApiRegistrationProfile registrationProfile);
}

@ -0,0 +1,78 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.output.adapter.websocket.authorization.client.dto;
/**
* This class represents the data that are required to register
* the oauth application.
*/
public class ApiRegistrationProfile {
public String applicationName;
public String tags[];
public boolean isAllowedToAllDomains;
public String consumerKey;
public String consumerSecret;
public boolean isMappingAnExistingOAuthApp;
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public boolean isAllowedToAllDomains() {
return isAllowedToAllDomains;
}
public void setIsAllowedToAllDomains(boolean isAllowedToAllDomains) {
this.isAllowedToAllDomains = isAllowedToAllDomains;
}
public boolean isMappingAnExistingOAuthApp() {
return isMappingAnExistingOAuthApp;
}
public void setIsMappingAnExistingOAuthApp(boolean isMappingAnExistingOAuthApp) {
this.isMappingAnExistingOAuthApp = isMappingAnExistingOAuthApp;
}
public String getConsumerKey() {
return consumerKey;
}
public void setConsumerKey(String consumerKey) {
this.consumerKey = consumerKey;
}
public String getConsumerSecret() {
return consumerSecret;
}
public void setConsumerSecret(String consumerSecret) {
this.consumerSecret = consumerSecret;
}
}

@ -0,0 +1,59 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.output.adapter.websocket.authorization.client.dto;
import java.util.List;
/**
* DTO of the authorization request
*/
public class AuthorizationRequest {
String tenantDomain;
String username;
List<DeviceIdentifier> deviceIdentifiers;
List<String> permissions;
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public List<DeviceIdentifier> getDeviceIdentifiers() {
return deviceIdentifiers;
}
public void setDeviceIdentifiers(List<DeviceIdentifier> deviceIdentifiers) {
this.deviceIdentifiers = deviceIdentifiers;
}
public List<String> getPermissions() {
return permissions;
}
public void setPermissions(List<String> permissions) {
this.permissions = permissions;
}
}

@ -0,0 +1,41 @@
/*
* 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.output.adapter.websocket.authorization.client.dto;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/admin/authorization")
/**
* This interface provided the definition of the device - user access verification service.
*/
public interface DeviceAccessAuthorizationAdminService {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
DeviceAuthorizationResult isAuthorized(AuthorizationRequest authorizationRequest);
}

@ -0,0 +1,56 @@
/*
* Copyright (c) 2015, 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.output.adapter.websocket.authorization.client.dto;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a DeviceAuthorizationResult including a list of authorized devices and a list of unauthorized devices.
*/
public class DeviceAuthorizationResult {
private List<DeviceIdentifier> authorizedDevices = new ArrayList<>();
private List<DeviceIdentifier> unauthorizedDevices = new ArrayList<>();
public List<DeviceIdentifier> getAuthorizedDevices() {
return authorizedDevices;
}
public void setAuthorizedDevices(List<DeviceIdentifier> authorizedDevices) {
this.authorizedDevices = authorizedDevices;
}
public void setUnauthorizedDevices(
List<DeviceIdentifier> unauthorizedDevices) {
this.unauthorizedDevices = unauthorizedDevices;
}
public void addAuthorizedDevice(DeviceIdentifier deviceIdentifier) {
authorizedDevices.add(deviceIdentifier);
}
public List<DeviceIdentifier> getUnauthorizedDevices() {
return unauthorizedDevices;
}
public void addUnauthorizedDevice(DeviceIdentifier deviceIdentifier) {
unauthorizedDevices.add(deviceIdentifier);
}
}

@ -0,0 +1,51 @@
/*
* Copyright (c) 2014, 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.output.adapter.websocket.authorization.client.dto;
import java.io.Serializable;
/**
* DTO of the device identifier
*/
public class DeviceIdentifier implements Serializable{
private String id;
private String type;
public DeviceIdentifier() {}
public DeviceIdentifier(String id, String type) {
this.id = id;
this.type = type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type.toLowerCase();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}

@ -0,0 +1,58 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.output.adapter.websocket.authorization.client.dto;
/**
* This class represents an OAuth application populated with necessary data.
*/
public class OAuthApplicationInfo {
public String client_id;
public String client_name;
public String callback_url;
public String client_secret;
public String getClient_id() {
return client_id;
}
public void setClient_id(String client_id) {
this.client_id = client_id;
}
public String getClient_name() {
return client_name;
}
public void setClient_name(String client_name) {
this.client_name = client_name;
}
public String getCallback_url() {
return callback_url;
}
public void setCallback_url(String callback_url) {
this.callback_url = callback_url;
}
public String getClient_secret() {
return client_secret;
}
public void setClient_secret(String client_secret) {
this.client_secret = client_secret;
}
}

@ -0,0 +1,40 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.output.adapter.websocket.authorization.client.dto;
/**
* This holds the data related to registration.
*/
public class RegisterInfo {
private boolean isRegistered;
private String msg;
public boolean isRegistered() {
return isRegistered;
}
public void setIsRegistered(boolean isRegistered) {
this.isRegistered = isRegistered;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

@ -0,0 +1,78 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.output.adapter.websocket.authorization.client.dto;
/**
* This class represents the data that are required to register
* the oauth application.
*/
public class RegistrationProfile {
public String callbackUrl;
public String clientName;
public String tokenScope;
public String owner;
public String grantType;
public String applicationType;
public String getCallbackUrl() {
return callbackUrl;
}
public void setCallbackUrl(String callBackUrl) {
this.callbackUrl = callBackUrl;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getTokenScope() {
return tokenScope;
}
public void setTokenScope(String tokenScope) {
this.tokenScope = tokenScope;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getGrantType() {
return grantType;
}
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public String getApplicationType() {
return applicationType;
}
public void setApplicationType(String applicationType) {
this.applicationType = applicationType;
}
}

@ -0,0 +1,52 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.
*
*/
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.output.adapter.websocket.authorization.client.dto;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
/**
* This hold the api defintion that is used as a contract with netflix feign.
*/
@Path("/token")
public interface TokenIssuerService {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
AccessTokenInfo getToken(@QueryParam("grant_type") String grant, @QueryParam("username") String username,
@QueryParam("password") String password);
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
AccessTokenInfo getToken(@QueryParam("grant_type") String grant, @QueryParam("refresh_token") String refreshToken);
}

@ -18,6 +18,8 @@
package org.wso2.carbon.device.mgt.output.adapter.websocket.config; package org.wso2.carbon.device.mgt.output.adapter.websocket.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.wso2.carbon.device.mgt.output.adapter.websocket.util.WebsocketUtils; import org.wso2.carbon.device.mgt.output.adapter.websocket.util.WebsocketUtils;
import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.CarbonUtils;
@ -34,6 +36,7 @@ public class WebsocketConfig {
private static WebsocketConfig config = new WebsocketConfig(); private static WebsocketConfig config = new WebsocketConfig();
private WebsocketValidationConfigs websocketValidationConfigs; private WebsocketValidationConfigs websocketValidationConfigs;
private static final Log log = LogFactory.getLog(WebsocketConfig.class);
private static final String WEBSOCKET_VALIDATION_CONFIG_PATH = private static final String WEBSOCKET_VALIDATION_CONFIG_PATH =
CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "websocket-validation.xml"; CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "websocket-validation.xml";
@ -62,6 +65,13 @@ public class WebsocketConfig {
} }
public WebsocketValidationConfigs getWebsocketValidationConfigs() { public WebsocketValidationConfigs getWebsocketValidationConfigs() {
if (websocketValidationConfigs == null) {
try {
init();
} catch (WebsocketValidationConfigurationFailedException e) {
log.error("failed to initialize the config", e);
}
}
return websocketValidationConfigs; return websocketValidationConfigs;
} }

@ -58,6 +58,26 @@
<groupId>commons-lang</groupId> <groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId> <artifactId>commons-lang</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>javax.cache.wso2</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -95,9 +115,20 @@
org.wso2.carbon.user.core.service, org.wso2.carbon.user.core.service,
org.wso2.carbon.user.core.tenant, org.wso2.carbon.user.core.tenant,
org.wso2.carbon.user.api, org.wso2.carbon.user.api,
*;resolution:=optional feign,
feign.auth,
feign.codec,
feign.gson,
javax.cache,
javax.xml.namespace,
javax.xml.stream,
org.wso2.carbon.base,
org.wso2.carbon.utils
</Import-Package> </Import-Package>
<DynamicImport-Package>*</DynamicImport-Package> <Embed-Dependency>
jsr311-api,
feign-jaxrs
</Embed-Dependency>
</instructions> </instructions>
</configuration> </configuration>
</plugin> </plugin>

@ -18,34 +18,63 @@
package org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization; package org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization;
import feign.Feign;
import feign.FeignException;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import feign.jaxrs.JAXRSContract;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.dna.mqtt.moquette.server.IAuthorizer; import org.dna.mqtt.moquette.server.IAuthorizer;
import org.wso2.andes.configuration.enums.MQTTAuthoriztionPermissionLevel; import org.wso2.andes.configuration.enums.MQTTAuthoriztionPermissionLevel;
import org.wso2.andes.mqtt.MQTTAuthorizationSubject; import org.wso2.andes.mqtt.MQTTAuthorizationSubject;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.client.OAuthRequestInterceptor;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.client.dto.AuthorizationRequest;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.client.dto.DeviceAccessAuthorizationAdminService;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.client.dto.DeviceAuthorizationResult;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.client.dto.DeviceIdentifier;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.config.AuthorizationConfigurationManager; import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.config.AuthorizationConfigurationManager;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.internal.AuthorizationDataHolder; import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.internal.AuthorizationDataHolder;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.util.AuthorizationCacheKey;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserRealm;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
import javax.cache.Cache;
import javax.cache.CacheConfiguration;
import javax.cache.CacheManager;
import javax.cache.Caching;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
/** /**
* Authorize the connecting users against Carbon Permission Model. Intended usage is * Authorize the connecting users against CDMF. Intended usage is
* via providing fully qualified class name in broker.xml * via providing fully qualified class name in broker.xml
* <p/> * <p/>
* This is just a simple authorization model. For dynamic topics use an implementation based on IAuthorizer * This is just a simple authorization model. For dynamic topics use an implementation based on IAuthorizer
*/ */
public class DeviceAccessBasedMQTTAuthorizer implements IAuthorizer { public class DeviceAccessBasedMQTTAuthorizer implements IAuthorizer {
private static final String SCOPE_IDENTIFIER = "scope";
private static final String UI_EXECUTE = "ui.execute"; private static final String UI_EXECUTE = "ui.execute";
private static Log logger = LogFactory.getLog(DeviceAccessBasedMQTTAuthorizer.class); private static Log logger = LogFactory.getLog(DeviceAccessBasedMQTTAuthorizer.class);
AuthorizationConfigurationManager MQTTAuthorizationConfiguration; AuthorizationConfigurationManager MQTTAuthorizationConfiguration;
private static final String CDMF_SERVER_BASE_CONTEXT = "/api/device-mgt/v1.0";
private static final String CACHE_MANAGER_NAME = "mqttAuthorizationCacheManager";
private static final String CACHE_NAME = "mqttAuthorizationCache";
private static DeviceAccessAuthorizationAdminService deviceAccessAuthorizationAdminService;
private static Cache<AuthorizationCacheKey, Boolean> cache;
public DeviceAccessBasedMQTTAuthorizer() { public DeviceAccessBasedMQTTAuthorizer() {
this.MQTTAuthorizationConfiguration = AuthorizationConfigurationManager.getInstance(); this.MQTTAuthorizationConfiguration = AuthorizationConfigurationManager.getInstance();
createCache();
deviceAccessAuthorizationAdminService = Feign.builder()
.requestInterceptor(new OAuthRequestInterceptor())
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(DeviceAccessAuthorizationAdminService.class,
MQTTAuthorizationConfiguration.getDeviceMgtServerUrl() + CDMF_SERVER_BASE_CONTEXT);
} }
/** /**
@ -54,35 +83,81 @@ public class DeviceAccessBasedMQTTAuthorizer implements IAuthorizer {
@Override @Override
public boolean isAuthorizedForTopic(MQTTAuthorizationSubject authorizationSubject, String topic, public boolean isAuthorizedForTopic(MQTTAuthorizationSubject authorizationSubject, String topic,
MQTTAuthoriztionPermissionLevel permissionLevel) { MQTTAuthoriztionPermissionLevel permissionLevel) {
if (isUserAuthorized(authorizationSubject, MQTTAuthorizationConfiguration.getAdminPermission(), UI_EXECUTE)) { PrivilegedCarbonContext.startTenantFlow();
return true; PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
} MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
String topics[] = topic.split("/"); try {
if (topics.length < 3) { String topics[] = topic.split("/");
return false; String tenantDomainFromTopic = topics[0];
} if (!tenantDomainFromTopic.equals(authorizationSubject.getTenantDomain())) {
String tenantIdFromTopic = topics[0]; return false;
if (!tenantIdFromTopic.equals(authorizationSubject.getTenantDomain())) { }
return false; if (topics.length < 3) {
} AuthorizationCacheKey authorizationCacheKey = new AuthorizationCacheKey(tenantDomainFromTopic
String deviceType = topics[1]; , authorizationSubject.getUsername(), "", "");
String deviceId = topics[2]; if (cache.get(authorizationCacheKey) != null && cache.get(authorizationCacheKey)) {
Object scopeObject = authorizationSubject.getProperties().get(SCOPE_IDENTIFIER); return true;
}
AuthorizationRequest authorizationRequest = new AuthorizationRequest();
authorizationRequest.setTenantDomain(tenantDomainFromTopic);
try {
DeviceAuthorizationResult deviceAuthorizationResult =
deviceAccessAuthorizationAdminService.isAuthorized(authorizationRequest);
if (deviceAuthorizationResult != null) {
cache.put(authorizationCacheKey, true);
return true;
}
return false;
} catch (FeignException e) {
logger.error(e.getMessage(), e);
return false;
}
}
String deviceType = topics[1];
String deviceId = topics[2];
AuthorizationCacheKey authorizationCacheKey = new AuthorizationCacheKey(tenantDomainFromTopic
, authorizationSubject.getUsername(), deviceId, deviceType);
if (cache.get(authorizationCacheKey) != null && cache.get(authorizationCacheKey)) {
return true;
}
if (!deviceId.isEmpty() && !deviceType.isEmpty() && scopeObject != null) { List<String> requiredPermission;
List<String> scopes = (List<String>) scopeObject;
String permissionScope = MQTTAuthorizationConfiguration.getMQTTPublisherScopeIdentifier();
if (permissionLevel == MQTTAuthoriztionPermissionLevel.SUBSCRIBE) { if (permissionLevel == MQTTAuthoriztionPermissionLevel.SUBSCRIBE) {
permissionScope = MQTTAuthorizationConfiguration.getMQTTSubscriberScopeIdentifier(); requiredPermission = MQTTAuthorizationConfiguration.getSubscriberPermissions();
} else {
requiredPermission = MQTTAuthorizationConfiguration.getPublisherPermissions();
} }
String requiredScope = MQTTAuthorizationConfiguration.getDevicemgtScopeIdentifier() + ":" + deviceType + ":"
+ deviceId + ":" + permissionScope; AuthorizationRequest authorizationRequest = new AuthorizationRequest();
for (String scope : scopes) { authorizationRequest.setTenantDomain(tenantDomainFromTopic);
if (requiredScope.equals(scope)) { if (requiredPermission != null) {
return true; authorizationRequest.setPermissions(requiredPermission);
}
authorizationRequest.setUsername(authorizationSubject.getUsername());
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(deviceType);
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>();
deviceIdentifiers.add(deviceIdentifier);
authorizationRequest.setDeviceIdentifiers(deviceIdentifiers);
try {
DeviceAuthorizationResult deviceAuthorizationResult =
deviceAccessAuthorizationAdminService.isAuthorized(authorizationRequest);
List<DeviceIdentifier> devices = deviceAuthorizationResult.getAuthorizedDevices();
if (devices != null && devices.size() > 0) {
DeviceIdentifier authorizedDevice = devices.get(0);
if (authorizedDevice.getId().equals(deviceId) && authorizedDevice.getType().equals(deviceType)) {
cache.put(authorizationCacheKey, true);
return true;
}
} }
} catch (FeignException e) {
logger.error(e.getMessage(), e);
} }
} finally {
PrivilegedCarbonContext.endTenantFlow();
} }
return false; return false;
} }
@ -91,6 +166,11 @@ public class DeviceAccessBasedMQTTAuthorizer implements IAuthorizer {
*/ */
@Override @Override
public boolean isAuthorizedToConnect(MQTTAuthorizationSubject authorizationSubject) { public boolean isAuthorizedToConnect(MQTTAuthorizationSubject authorizationSubject) {
if (MQTTAuthorizationConfiguration.getConnectionPermission() == null ||
MQTTAuthorizationConfiguration.getConnectionPermission().isEmpty()) {
//allow authenticated client to connect.
return true;
}
return isUserAuthorized(authorizationSubject, MQTTAuthorizationConfiguration.getConnectionPermission() return isUserAuthorized(authorizationSubject, MQTTAuthorizationConfiguration.getConnectionPermission()
, UI_EXECUTE); , UI_EXECUTE);
} }
@ -122,4 +202,28 @@ public class DeviceAccessBasedMQTTAuthorizer implements IAuthorizer {
PrivilegedCarbonContext.endTenantFlow(); PrivilegedCarbonContext.endTenantFlow();
} }
} }
/**
* This method is used to create the Caches.
* @return Cachemanager
*/
private void createCache() {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
try {
CacheManager cacheManager = Caching.getCacheManagerFactory().getCacheManager(CACHE_MANAGER_NAME);
if (MQTTAuthorizationConfiguration.getCacheDuration() == 0) {
cache = cacheManager.getCache(CACHE_NAME);
} else {
cache = cacheManager.<AuthorizationCacheKey, Boolean>createCacheBuilder(CACHE_NAME).
setExpiry(CacheConfiguration.ExpiryType.MODIFIED, new CacheConfiguration.Duration(
TimeUnit.SECONDS, MQTTAuthorizationConfiguration.getCacheDuration())).
setStoreByValue(false).build();
}
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
} }

@ -0,0 +1,91 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.andes.extensions.device.mgt.mqtt.authorization.client;
import feign.Feign;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.auth.BasicAuthRequestInterceptor;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import feign.jaxrs.JAXRSContract;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.client.dto.AccessTokenInfo;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.client.dto.ApiApplicationKey;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.client.dto.ApiApplicationRegistrationService;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.client.dto.ApiRegistrationProfile;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.client.dto.TokenIssuerService;
import org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.config.AuthorizationConfigurationManager;
/**
* This is a request interceptor to add oauth token header.
*/
public class OAuthRequestInterceptor implements RequestInterceptor {
private AccessTokenInfo tokenInfo;
private long refreshTimeOffset;
private static final String API_APPLICATION_REGISTRATION_CONTEXT = "/api-application-registration";
private static final String DEVICE_MANAGEMENT_SERVICE_TAG[] = {"device_management"};
private static final String APPLICATION_NAME = "mqtt_broker";
private static final String PASSWORD_GRANT_TYPE = "password";
private static final String REFRESH_GRANT_TYPE = "refresh_token";
private ApiApplicationRegistrationService apiApplicationRegistrationService;
private TokenIssuerService tokenIssuerService;
/**
* Creates an interceptor that authenticates all requests.
*/
public OAuthRequestInterceptor() {
refreshTimeOffset = AuthorizationConfigurationManager.getInstance().getTokenRefreshTimeOffset();
String username = AuthorizationConfigurationManager.getInstance().getUsername();
String password = AuthorizationConfigurationManager.getInstance().getPassword();
apiApplicationRegistrationService = Feign.builder().requestInterceptor(
new BasicAuthRequestInterceptor(username, password))
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(ApiApplicationRegistrationService.class,
AuthorizationConfigurationManager.getInstance().getDeviceMgtServerUrl() +
API_APPLICATION_REGISTRATION_CONTEXT);
}
@Override
public void apply(RequestTemplate template) {
if (tokenInfo == null) {
//had to do on demand initialization due to start up error.
ApiRegistrationProfile apiRegistrationProfile = new ApiRegistrationProfile();
apiRegistrationProfile.setApplicationName(APPLICATION_NAME);
apiRegistrationProfile.setIsAllowedToAllDomains(false);
apiRegistrationProfile.setIsMappingAnExistingOAuthApp(false);
apiRegistrationProfile.setTags(DEVICE_MANAGEMENT_SERVICE_TAG);
ApiApplicationKey apiApplicationKey = apiApplicationRegistrationService.register(apiRegistrationProfile);
String consumerKey = apiApplicationKey.getConsumerKey();
String consumerSecret = apiApplicationKey.getConsumerSecret();
String username = AuthorizationConfigurationManager.getInstance().getUsername();
String password = AuthorizationConfigurationManager.getInstance().getPassword();
tokenIssuerService = Feign.builder().requestInterceptor(
new BasicAuthRequestInterceptor(consumerKey, consumerSecret))
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(TokenIssuerService.class, AuthorizationConfigurationManager.getInstance().getTokenEndpoint());
tokenInfo = tokenIssuerService.getToken(PASSWORD_GRANT_TYPE, username, password);
tokenInfo.setExpires_in(System.currentTimeMillis() + tokenInfo.getExpires_in());
}
if (System.currentTimeMillis() + refreshTimeOffset > tokenInfo.getExpires_in()) {
tokenInfo = tokenIssuerService.getToken(REFRESH_GRANT_TYPE, tokenInfo.getRefresh_token());
tokenInfo.setExpires_in(System.currentTimeMillis() + tokenInfo.getExpires_in());
}
String headerValue = "Bearer " + tokenInfo.getAccess_token();
template.header("Authorization", headerValue);
}
}

@ -0,0 +1,57 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
/**
* This hold access token info that returned from the api call
*/
public class AccessTokenInfo {
public String token_type;
public long expires_in;
public String refresh_token;
public String access_token;
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
public long getExpires_in() {
return expires_in;
}
public void setExpires_in(long expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
}

@ -0,0 +1,43 @@
/*
* 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
/**
* This holds api application consumer key and secret.
*/
public class ApiApplicationKey {
private String client_id;
private String client_secret;
public String getConsumerKey() {
return this.client_id;
}
public void setClient_id(String consumerKey) {
this.client_id = consumerKey;
}
public String getConsumerSecret() {
return this.client_secret;
}
public void setClient_secret(String consumerSecret) {
this.client_secret = consumerSecret;
}
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* This is the application registration service that exposed for apimApplicationRegistration
*/
@Path("/register")
public interface ApiApplicationRegistrationService {
/**
* This method is used to register api application
*
* @param registrationProfile contains the necessary attributes that are needed in order to register an app.
*/
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
ApiApplicationKey register(ApiRegistrationProfile registrationProfile);
}

@ -0,0 +1,78 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
/**
* This class represents the data that are required to register
* the oauth application.
*/
public class ApiRegistrationProfile {
public String applicationName;
public String tags[];
public boolean isAllowedToAllDomains;
public String consumerKey;
public String consumerSecret;
public boolean isMappingAnExistingOAuthApp;
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public boolean isAllowedToAllDomains() {
return isAllowedToAllDomains;
}
public void setIsAllowedToAllDomains(boolean isAllowedToAllDomains) {
this.isAllowedToAllDomains = isAllowedToAllDomains;
}
public boolean isMappingAnExistingOAuthApp() {
return isMappingAnExistingOAuthApp;
}
public void setIsMappingAnExistingOAuthApp(boolean isMappingAnExistingOAuthApp) {
this.isMappingAnExistingOAuthApp = isMappingAnExistingOAuthApp;
}
public String getConsumerKey() {
return consumerKey;
}
public void setConsumerKey(String consumerKey) {
this.consumerKey = consumerKey;
}
public String getConsumerSecret() {
return consumerSecret;
}
public void setConsumerSecret(String consumerSecret) {
this.consumerSecret = consumerSecret;
}
}

@ -0,0 +1,59 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
import java.util.List;
/**
* DTO of the authorization request
*/
public class AuthorizationRequest {
String tenantDomain;
String username;
List<DeviceIdentifier> deviceIdentifiers;
List<String> permissions;
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public List<DeviceIdentifier> getDeviceIdentifiers() {
return deviceIdentifiers;
}
public void setDeviceIdentifiers(List<DeviceIdentifier> deviceIdentifiers) {
this.deviceIdentifiers = deviceIdentifiers;
}
public List<String> getPermissions() {
return permissions;
}
public void setPermissions(List<String> permissions) {
this.permissions = permissions;
}
}

@ -0,0 +1,41 @@
/*
* 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/admin/authorization")
/**
* This interface provided the definition of the device - user access verification service.
*/
public interface DeviceAccessAuthorizationAdminService {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
DeviceAuthorizationResult isAuthorized(AuthorizationRequest authorizationRequest);
}

@ -0,0 +1,56 @@
/*
* Copyright (c) 2015, 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a DeviceAuthorizationResult including a list of authorized devices and a list of unauthorized devices.
*/
public class DeviceAuthorizationResult {
private List<DeviceIdentifier> authorizedDevices = new ArrayList<>();
private List<DeviceIdentifier> unauthorizedDevices = new ArrayList<>();
public List<DeviceIdentifier> getAuthorizedDevices() {
return authorizedDevices;
}
public void setAuthorizedDevices(List<DeviceIdentifier> authorizedDevices) {
this.authorizedDevices = authorizedDevices;
}
public void setUnauthorizedDevices(
List<DeviceIdentifier> unauthorizedDevices) {
this.unauthorizedDevices = unauthorizedDevices;
}
public void addAuthorizedDevice(DeviceIdentifier deviceIdentifier) {
authorizedDevices.add(deviceIdentifier);
}
public List<DeviceIdentifier> getUnauthorizedDevices() {
return unauthorizedDevices;
}
public void addUnauthorizedDevice(DeviceIdentifier deviceIdentifier) {
unauthorizedDevices.add(deviceIdentifier);
}
}

@ -0,0 +1,51 @@
/*
* Copyright (c) 2014, 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
import java.io.Serializable;
/**
* DTO of the device identifier
*/
public class DeviceIdentifier implements Serializable{
private String id;
private String type;
public DeviceIdentifier() {}
public DeviceIdentifier(String id, String type) {
this.id = id;
this.type = type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type.toLowerCase();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}

@ -0,0 +1,58 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
/**
* This class represents an OAuth application populated with necessary data.
*/
public class OAuthApplicationInfo {
public String client_id;
public String client_name;
public String callback_url;
public String client_secret;
public String getClient_id() {
return client_id;
}
public void setClient_id(String client_id) {
this.client_id = client_id;
}
public String getClient_name() {
return client_name;
}
public void setClient_name(String client_name) {
this.client_name = client_name;
}
public String getCallback_url() {
return callback_url;
}
public void setCallback_url(String callback_url) {
this.callback_url = callback_url;
}
public String getClient_secret() {
return client_secret;
}
public void setClient_secret(String client_secret) {
this.client_secret = client_secret;
}
}

@ -0,0 +1,40 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
/**
* This holds the data related to registration.
*/
public class RegisterInfo {
private boolean isRegistered;
private String msg;
public boolean isRegistered() {
return isRegistered;
}
public void setIsRegistered(boolean isRegistered) {
this.isRegistered = isRegistered;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

@ -0,0 +1,78 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
/**
* This class represents the data that are required to register
* the oauth application.
*/
public class RegistrationProfile {
public String callbackUrl;
public String clientName;
public String tokenScope;
public String owner;
public String grantType;
public String applicationType;
public String getCallbackUrl() {
return callbackUrl;
}
public void setCallbackUrl(String callBackUrl) {
this.callbackUrl = callBackUrl;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getTokenScope() {
return tokenScope;
}
public void setTokenScope(String tokenScope) {
this.tokenScope = tokenScope;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getGrantType() {
return grantType;
}
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public String getApplicationType() {
return applicationType;
}
public void setApplicationType(String applicationType) {
this.applicationType = applicationType;
}
}

@ -0,0 +1,40 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.andes.extensions.device.mgt.mqtt.authorization.client.dto;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
/**
* This hold the api defintion that is used as a contract with netflix feign.
*/
@Path("/token")
public interface TokenIssuerService {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
AccessTokenInfo getToken(@QueryParam("grant_type") String grant, @QueryParam("username") String username,
@QueryParam("password") String password);
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
AccessTokenInfo getToken(@QueryParam("grant_type") String grant, @QueryParam("refresh_token") String refreshToken);
}

@ -21,23 +21,34 @@ package org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.config;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class AuthorizationConfigurationManager { public class AuthorizationConfigurationManager {
private static final String CONNECTION_PERMISSION = "connectionPermission"; private static final String CONNECTION_PERMISSION = "connectionPermission";
private static final String ADMIN_PERMISSION = "adminPermission"; private static final String MQTT_PUBLISHER_PERMISSION = "publisherPermission";
private static final String MQTT_PUBLISHER_SCOPE_IDENTIFIER = "MQTTPublisherScopeIdentifier"; private static final String MQTT_SUBSCRIBER_PERMISSION = "subscriberPermission";
private static final String MQTT_SUBSCRIBER_SCOPE_IDENTIFIER = "MQTTSubscriberScopeIdentifier"; private static final String CONNECTION_USERNAME = "username";
private static final String DEVICE_MGT_SCOPE_IDENTIFIER = "devicemgtScopeIdentifier"; private static final String CONNECTION_PASSWORD = "password";
private static final String TOKEN_ENDPOINT = "tokenEndpoint";
private static final String TOKEN_REFRESH_TIME_OFFSET = "tokenRefreshTimeOffset";
private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl";
private static final String MQTT_CACHE_DURATION = "cacheDurationSeconds";
private static final AuthorizationConfigurationManager oAuthConfigurationManager private static final AuthorizationConfigurationManager oAuthConfigurationManager
= new AuthorizationConfigurationManager(); = new AuthorizationConfigurationManager();
private static Log logger = LogFactory.getLog(AuthorizationConfigurationManager.class); private static Log logger = LogFactory.getLog(AuthorizationConfigurationManager.class);
private String connectionPermission; private String connectionPermission;
private String adminPermission; private String username;
private String MQTTPublisherScopeIdentifier; private String password;
private String MQTTSubscriberScopeIdentifier; private String tokenEndpoint;
private String devicemgtScopeIdentifier; private long tokenRefreshTimeOffset;
private String deviceMgtServerUrl;
private long cacheDuration;
private List<String> publisherPermissions = new ArrayList<>();
private List<String> subscriberPermissions = new ArrayList<>();
private AuthorizationConfigurationManager() { private AuthorizationConfigurationManager() {
@ -59,51 +70,104 @@ public class AuthorizationConfigurationManager {
} }
} }
public String getAdminPermission() { public List<String> getPublisherPermissions() {
return adminPermission; return publisherPermissions;
} }
public void setAdminPermission(String adminPermission) { public void setPublisherPermission(String publisherPermission) {
if (adminPermission != null) { if (publisherPermission != null && !publisherPermission.isEmpty()) {
this.adminPermission = adminPermission; this.publisherPermissions.add(publisherPermission);
} else { } else {
logger.error("admin permission can't be null "); logger.error("MQTT publisher permission can't be empty ");
} }
} }
public String getMQTTPublisherScopeIdentifier() { public List<String> getSubscriberPermissions() {
return MQTTPublisherScopeIdentifier; return subscriberPermissions;
} }
public void setMQTTPublisherScopeIdentifier(String MQTTPublisherScopeIdentifier) { public void setSubscriberPermission(String subscriberPermission) {
if (MQTTPublisherScopeIdentifier != null) { if (subscriberPermission != null && !subscriberPermission.isEmpty()) {
this.MQTTPublisherScopeIdentifier = MQTTPublisherScopeIdentifier; this.subscriberPermissions.add(subscriberPermission);
} else { } else {
logger.error("MQTT publisher scope identifier can't be null "); logger.error("MQTT subscriber permissions can't be null ");
} }
} }
public String getMQTTSubscriberScopeIdentifier() { public String getUsername() {
return MQTTSubscriberScopeIdentifier; return username;
}
public void setUsername(String username) {
if (username != null && !username.isEmpty()) {
this.username = username;
} else {
logger.error("username can't be empty ");
}
}
public String getPassword() {
return password;
} }
public void setMQTTSubscriberScopeIdentifier(String MQTTSubscriberScopeIdentifier) { public void setPassword(String password) {
if (MQTTSubscriberScopeIdentifier != null) { if (password != null && !password.isEmpty()) {
this.MQTTSubscriberScopeIdentifier = MQTTSubscriberScopeIdentifier; this.password = password;
} else { } else {
logger.error("MQTT subscriber scope identifier can't be null "); logger.error("password can't be empty ");
} }
} }
public String getDevicemgtScopeIdentifier() { public String getTokenEndpoint() {
return devicemgtScopeIdentifier; return tokenEndpoint;
} }
public void setDevicemgtScopeIdentifier(String devicemgtScopeIdentifier) { public void setTokenEndpoint(String tokenEndpoint) {
if (devicemgtScopeIdentifier != null) { if (tokenEndpoint != null && !tokenEndpoint.isEmpty()) {
this.devicemgtScopeIdentifier = devicemgtScopeIdentifier; this.tokenEndpoint = tokenEndpoint;
} else { } else {
logger.error("Device management scope identifier can't be null "); logger.error("tokenEndpoint can't be empty ");
}
}
public long getTokenRefreshTimeOffset() {
return tokenRefreshTimeOffset;
}
public void setTokenRefreshTimeOffset(String tokenRefreshTimeOffset) {
try {
if (tokenRefreshTimeOffset != null && !tokenRefreshTimeOffset.isEmpty()) {
this.tokenRefreshTimeOffset = Long.parseLong(tokenRefreshTimeOffset);
}
} catch (NumberFormatException e) {
logger.error("tokenRefreshTimeOffset is not a number(long)");
}
}
public String getDeviceMgtServerUrl() {
return deviceMgtServerUrl;
}
public void setDeviceMgtServerUrl(String deviceMgtServerUrl) {
if (deviceMgtServerUrl != null && !deviceMgtServerUrl.isEmpty()) {
this.deviceMgtServerUrl = deviceMgtServerUrl;
} else {
logger.error("deviceMgtServerUrl can't be empty ");
}
}
public long getCacheDuration() {
return cacheDuration;
}
public void setCacheDuration(String cacheDuration) {
try {
if (cacheDuration != null && !cacheDuration.isEmpty()) {
this.cacheDuration = Long.parseLong(cacheDuration);
}
} catch (NumberFormatException e) {
this.cacheDuration = 0;
} }
} }
@ -120,18 +184,32 @@ public class AuthorizationConfigurationManager {
case CONNECTION_PERMISSION: case CONNECTION_PERMISSION:
setConnectionPermission(propertyValue); setConnectionPermission(propertyValue);
break; break;
case ADMIN_PERMISSION: case MQTT_PUBLISHER_PERMISSION:
setAdminPermission(propertyValue); setPublisherPermission(propertyValue);
break;
case MQTT_SUBSCRIBER_PERMISSION:
setSubscriberPermission(propertyValue);
break;
case CONNECTION_USERNAME:
setUsername(propertyValue);
break; break;
case MQTT_PUBLISHER_SCOPE_IDENTIFIER: case CONNECTION_PASSWORD:
setMQTTPublisherScopeIdentifier(propertyValue); setPassword(propertyValue);
break; break;
case MQTT_SUBSCRIBER_SCOPE_IDENTIFIER: case TOKEN_ENDPOINT:
setMQTTSubscriberScopeIdentifier(propertyValue); setTokenEndpoint(propertyValue);
break; break;
case DEVICE_MGT_SCOPE_IDENTIFIER: case TOKEN_REFRESH_TIME_OFFSET:
setDevicemgtScopeIdentifier(propertyValue); setTokenRefreshTimeOffset(propertyValue);
break; break;
case DEVICE_MGT_SERVER_URL:
setDeviceMgtServerUrl(propertyValue);
break;
case MQTT_CACHE_DURATION:
setCacheDuration(propertyValue);
break;
default: default:
break; break;
} }

@ -0,0 +1,33 @@
package org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization.util;
public class AuthorizationCacheKey {
String tenantDomain;
String deviceId;
String deviceType;
String username;
public AuthorizationCacheKey(String tenantDomain, String username, String deviceId, String deviceType) {
this.username = username;
this.tenantDomain = tenantDomain;
this.deviceId = deviceId;
this.deviceType = deviceType;
}
@Override
public int hashCode() {
int result = this.deviceType.hashCode();
result = 31 * result + ("@" + this.deviceId + "@" + this.tenantDomain + "@" + this.username).hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
return (obj instanceof AuthorizationCacheKey) && deviceType.equals(
((AuthorizationCacheKey) obj).deviceType) && tenantDomain.equals(
((AuthorizationCacheKey) obj).tenantDomain ) && deviceId.equals(
((AuthorizationCacheKey) obj).deviceId) && username.equals(
((AuthorizationCacheKey) obj).username);
}
}

@ -39,6 +39,18 @@
<groupId>org.wso2.carbon.devicemgt-plugins</groupId> <groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization</artifactId> <artifactId>org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
@ -66,6 +78,12 @@
<bundleDef> <bundleDef>
org.wso2.carbon.devicemgt-plugins:org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization:${carbon.devicemgt.plugins.version} org.wso2.carbon.devicemgt-plugins:org.wso2.carbon.andes.extensions.device.mgt.mqtt.authorization:${carbon.devicemgt.plugins.version}
</bundleDef> </bundleDef>
<bundleDef>
io.github.openfeign:feign-core:${io.github.openfeign.version}
</bundleDef>
<bundleDef>
io.github.openfeign:feign-gson:${io.github.openfeign.version}
</bundleDef>
</bundles> </bundles>
<importFeatures> <importFeatures>
<importFeatureDef>org.wso2.carbon.core.server:4.4.9</importFeatureDef> <importFeatureDef>org.wso2.carbon.core.server:4.4.9</importFeatureDef>

@ -68,6 +68,16 @@
<groupId>com.jayway.jsonpath</groupId> <groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId> <artifactId>json-path</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
<version>${io.github.openfeign.version}</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
<version>${io.github.openfeign.version}</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
@ -92,7 +102,7 @@
<outputDirectory> <outputDirectory>
${project.build.directory}/maven-shared-archive-resources/webapps/ ${project.build.directory}/maven-shared-archive-resources/webapps/
</outputDirectory> </outputDirectory>
<destFileName>secured-outputui.war</destFileName> <destFileName>secured-websocket.war</destFileName>
</artifactItem> </artifactItem>
</artifactItems> </artifactItems>
</configuration> </configuration>
@ -180,6 +190,12 @@
<bundleDef> <bundleDef>
com.jayway.jsonpath:json-path com.jayway.jsonpath:json-path
</bundleDef> </bundleDef>
<bundleDef>
io.github.openfeign:feign-core:${io.github.openfeign.version}
</bundleDef>
<bundleDef>
io.github.openfeign:feign-gson:${io.github.openfeign.version}
</bundleDef>
</bundles> </bundles>
<importFeatures> <importFeatures>
<importFeatureDef> <importFeatureDef>

@ -35,5 +35,16 @@
</Authenticator> </Authenticator>
<!--Authorizer holds the information of the authorizer that is used authorize a connection.--> <!--Authorizer holds the information of the authorizer that is used authorize a connection.-->
<Authorizer class="org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.DeviceAuthorizer"></Authorizer> <Authorizer class="org.wso2.carbon.device.mgt.output.adapter.websocket.authorization.DeviceAuthorizer">
<Properties>
<!--websocket connection permissions which are validated for grouping (can have multiple permission.)-->
<Property name="statsPermission">/permission/device-mgt/user/groups/device_monitor</Property>
<Property name="username">admin</Property>
<Property name="password">admin</Property>
<Property name="tokenEndpoint">https://localhost:9443/oauth2</Property>
<!--offset time from expiry time to trigger refresh call (in seconds)-->
<Property name="tokenRefreshTimeOffset">100</Property>
<Property name="deviceMgtServerUrl">https://localhost:9443</Property>
</Properties>
</Authorizer>
</WebsocketValidationConfigs> </WebsocketValidationConfigs>

@ -239,6 +239,11 @@
<artifactId>org.wso2.carbon.ndatasource.core</artifactId> <artifactId>org.wso2.carbon.ndatasource.core</artifactId>
<version>${carbon.kernel.version}</version> <version>${carbon.kernel.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>javax.cache.wso2</artifactId>
<version>${carbon.kernel.version}</version>
</dependency>
<!-- Device Management Core dependencies --> <!-- Device Management Core dependencies -->
<dependency> <dependency>
@ -1155,6 +1160,21 @@
<artifactId>commons-lang</artifactId> <artifactId>commons-lang</artifactId>
<version>${commons.lang.version}</version> <version>${commons.lang.version}</version>
</dependency> </dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>${io.github.openfeign.version}</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
<version>${io.github.openfeign.version}</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
<version>${io.github.openfeign.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
@ -1317,6 +1337,10 @@
<!-- MB Features --> <!-- MB Features -->
<carbon.messaging.version>3.1.11</carbon.messaging.version> <carbon.messaging.version>3.1.11</carbon.messaging.version>
<!--Feign Version-->
<io.github.openfeign.version>9.3.1</io.github.openfeign.version>
<javax.ws.rs.jsr311-api.version>[1.1.0, 2.0.0)</javax.ws.rs.jsr311-api.version>
</properties> </properties>
<scm> <scm>

Loading…
Cancel
Save