Merge pull request #319 from ayyoob/transport

Updated grant type implementation
4.x.x
Milan Perera 8 years ago committed by GitHub
commit c49dc435e1

@ -202,18 +202,13 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori
throws DeviceAccessAuthorizationException { throws DeviceAccessAuthorizationException {
//Check for device ownership. If the user is the owner of the device we allow the access. //Check for device ownership. If the user is the owner of the device we allow the access.
try { try {
Device device = DeviceManagementDataHolder.getInstance().getDeviceManagementProvider(). return DeviceManagementDataHolder.getInstance().getDeviceManagementProvider().
getDevice(deviceIdentifier); isEnrolled(deviceIdentifier, username);
EnrolmentInfo enrolmentInfo = device.getEnrolmentInfo();
if (enrolmentInfo != null && username.equalsIgnoreCase(enrolmentInfo.getOwner())) {
return true;
}
} catch (DeviceManagementException e) { } catch (DeviceManagementException e) {
throw new DeviceAccessAuthorizationException("Unable to authorize the access to device : " + throw new DeviceAccessAuthorizationException("Unable to authorize the access to device : " +
deviceIdentifier.getId() + " for the user : " + deviceIdentifier.getId() + " for the user : " +
username, e); username, e);
} }
return false;
} }
private boolean isAdminUser(String username, int tenantId) throws UserStoreException { private boolean isAdminUser(String username, int tenantId) throws UserStoreException {

@ -50,6 +50,10 @@
<groupId>org.wso2.carbon.apimgt</groupId> <groupId>org.wso2.carbon.apimgt</groupId>
<artifactId>org.wso2.carbon.apimgt.impl</artifactId> <artifactId>org.wso2.carbon.apimgt.impl</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.apimgt</groupId>
<artifactId>org.wso2.carbon.apimgt.keymgt</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.googlecode.json-simple.wso2</groupId> <groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId> <artifactId>json-simple</artifactId>
@ -95,40 +99,41 @@
org.wso2.carbon.device.mgt.*, org.wso2.carbon.device.mgt.*,
org.wso2.carbon.identity.application.common.model, org.wso2.carbon.identity.application.common.model,
org.wso2.carbon.identity.oauth.callback, org.wso2.carbon.identity.oauth.callback,
org.wso2.carbon.identity.oauth.common,
org.wso2.carbon.identity.oauth2, org.wso2.carbon.identity.oauth2,
org.wso2.carbon.identity.oauth2.model, org.wso2.carbon.identity.oauth2.model,
org.wso2.carbon.identity.oauth2.validators, org.wso2.carbon.identity.oauth2.validators,
org.wso2.carbon.user.api, org.wso2.carbon.user.api,
org.wso2.carbon.user.core.service, org.wso2.carbon.user.core.service,
org.wso2.carbon.identity.application.common.model,
org.wso2.carbon.identity.application.authentication.framework.model,
org.wso2.carbon.user.core.tenant, org.wso2.carbon.user.core.tenant,
org.json.simple, org.json.simple,
javax.cache, javax.cache,
javax.xml.namespace,
org.apache.axiom.om,
org.wso2.carbon.apimgt.api, org.wso2.carbon.apimgt.api,
org.wso2.carbon.apimgt.impl, org.wso2.carbon.apimgt.impl,
org.wso2.carbon.apimgt.impl.dao, org.wso2.carbon.apimgt.impl.dao,
org.wso2.carbon.apimgt.impl.utils, org.wso2.carbon.apimgt.impl.utils,
org.wso2.carbon.identity.application.common.cache,
org.wso2.carbon.identity.core.util, org.wso2.carbon.identity.core.util,
org.wso2.carbon.identity.oauth2.dto, org.wso2.carbon.identity.oauth2.dto,
org.wso2.carbon.identity.oauth2.token, org.wso2.carbon.identity.oauth2.token,
org.wso2.carbon.identity.oauth2.token.handlers.grant, org.apache.oltu.oauth2.common.validators,
org.wso2.carbon.user.core,
org.wso2.carbon.user.core.config,
org.wso2.carbon.user.core.util,
org.wso2.carbon.utils, org.wso2.carbon.utils,
org.wso2.carbon.context, org.wso2.carbon.context,
org.wso2.carbon.identity.oauth.cache, org.wso2.carbon.identity.oauth.cache,
org.wso2.carbon.identity.oauth.config, org.wso2.carbon.identity.oauth.config,
org.wso2.carbon.identity.oauth2.dao, org.wso2.carbon.identity.oauth2.dao,
org.wso2.carbon.utils.multitenancy, org.wso2.carbon.utils.multitenancy,
org.wso2.carbon.base,
org.wso2.carbon.identity.oauth2.grant.jwt.*, org.wso2.carbon.identity.oauth2.grant.jwt.*,
org.wso2.carbon.device.mgt.core.* org.wso2.carbon.device.mgt.core.*,
javax.xml.bind,
javax.xml.bind.annotation,
javax.xml.parsers,
org.w3c.dom,
org.wso2.carbon.apimgt.keymgt,
org.wso2.carbon.apimgt.keymgt.handlers,
com.google.gson,
org.apache.commons.codec.binary,
org.wso2.carbon.identity.application.authentication.framework.model,
org.apache.oltu.oauth2.common,
org.wso2.carbon.base
</Import-Package> </Import-Package>
</instructions> </instructions>
</configuration> </configuration>

@ -0,0 +1,30 @@
package org.wso2.carbon.device.mgt.oauth.extensions;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import java.util.List;
/**
* This class holds the request format for device for grant type.
*/
public class DeviceRequestDTO {
private List<DeviceIdentifier> deviceIdentifiers;
private String scope;
public List<DeviceIdentifier> getDeviceIdentifiers() {
return deviceIdentifiers;
}
public void setDeviceIdentifiers(List<DeviceIdentifier> deviceIdentifiers) {
this.deviceIdentifiers = deviceIdentifiers;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
}

@ -0,0 +1,13 @@
package org.wso2.carbon.device.mgt.oauth.extensions;
/**
* This hold the OAuthConstants related oauth extensions.
*/
public class OAuthConstants {
public static final String DEFAULT_DEVICE_ASSERTION = "device";
public static final String DEFAULT_USERNAME_IDENTIFIER = "username";
public static final String DEFAULT_PASSWORD_IDENTIFIER = "password";
}

@ -18,17 +18,25 @@
package org.wso2.carbon.device.mgt.oauth.extensions; package org.wso2.carbon.device.mgt.oauth.extensions;
import com.google.gson.Gson;
import org.apache.commons.codec.binary.Base64;
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.w3c.dom.Document;
import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.dao.ApiMgtDAO; import org.wso2.carbon.apimgt.impl.dao.ApiMgtDAO;
import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.apimgt.impl.utils.APIUtil;
import org.wso2.carbon.apimgt.keymgt.ScopesIssuer;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAuthorizationResult;
import org.wso2.carbon.device.mgt.oauth.extensions.config.DeviceMgtScopesConfig;
import org.wso2.carbon.device.mgt.oauth.extensions.config.DeviceMgtScopesConfigurationFailedException;
import org.wso2.carbon.device.mgt.oauth.extensions.internal.OAuthExtensionsDataHolder; import org.wso2.carbon.device.mgt.oauth.extensions.internal.OAuthExtensionsDataHolder;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.oauth2.model.RequestParameter;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext; import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.user.api.TenantManager; import org.wso2.carbon.user.api.TenantManager;
import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserRealm;
@ -36,6 +44,9 @@ import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
import javax.cache.Caching; import javax.cache.Caching;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -51,7 +62,8 @@ public class OAuthExtUtils {
private static final String UI_EXECUTE = "ui.execute"; private static final String UI_EXECUTE = "ui.execute";
private static final String REST_API_SCOPE_CACHE = "REST_API_SCOPE_CACHE"; private static final String REST_API_SCOPE_CACHE = "REST_API_SCOPE_CACHE";
private static final int START_INDEX = 0; private static final int START_INDEX = 0;
private static final String CDMF_SCOPE_SEPERATOR = "/"; private static final String DEFAULT_SCOPE_TAG = "device-mgt";
/** /**
* This method is used to get the tenant id when given tenant domain. * This method is used to get the tenant id when given tenant domain.
* *
@ -114,7 +126,7 @@ public class OAuthExtUtils {
restAPIScopesOfCurrentTenant = APIUtil. restAPIScopesOfCurrentTenant = APIUtil.
getRESTAPIScopesFromConfig(APIUtil.getTenantRESTAPIScopesConfig(tenantDomain)); getRESTAPIScopesFromConfig(APIUtil.getTenantRESTAPIScopesConfig(tenantDomain));
//call load tenant config for rest API. //call load tenant org.wso2.carbon.device.mgt.iot.output.adapter.ui.config for rest API.
//then put cache //then put cache
appScopes.putAll(restAPIScopesOfCurrentTenant); appScopes.putAll(restAPIScopesOfCurrentTenant);
Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER) Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER)
@ -166,20 +178,6 @@ public class OAuthExtUtils {
return false; return false;
} }
/**
* Determines if the scope is specified with CDMF device scope prefix.
*
* @param scope - The scope key to check
* @return - 'true' if the scope has the prefix. 'false' if not.
*/
private static boolean isCDMFDeviceSpecificScope(String scope) {
// load white listed scopes
if (scope.startsWith(OAuthExtensionsDataHolder.getInstance().getDeviceScope())) {
return true;
}
return false;
}
/** /**
* Get the set of default scopes. If a requested scope is matches with the patterns specified in the white list, * Get the set of default scopes. If a requested scope is matches with the patterns specified in the white list,
* then such scopes will be issued without further validation. If the scope list is empty, * then such scopes will be issued without further validation. If the scope list is empty,
@ -275,27 +273,6 @@ public class OAuthExtUtils {
else if (appScopes.containsKey(scope) || isWhiteListedScope(scope)) { else if (appScopes.containsKey(scope) || isWhiteListedScope(scope)) {
authorizedScopes.add(scope); authorizedScopes.add(scope);
} }
//check whether is device specific scope (CDMF)
else if (isCDMFDeviceSpecificScope(scope)) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
try {
String deviceId[] = scope.split(CDMF_SCOPE_SEPERATOR);
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(deviceId[2], deviceId[1]);
boolean enrolled = OAuthExtensionsDataHolder.getInstance().getDeviceManagementService().isEnrolled(
deviceIdentifier, tokReqMsgCtx.getAuthorizedUser().getUserName());
if (enrolled) {
authorizedScopes.add(scope);
}
} catch (DeviceManagementException e) {
log.error("Error occurred while checking device scope with CDMF", e);
} catch (ArrayIndexOutOfBoundsException e) {
log.error("Invalid scope format, have to adhere [prefix/devicetype/deviceId]", e);
}finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
} }
} catch (UserStoreException e) { } catch (UserStoreException e) {
log.error("Error occurred while initializing user store.", e); log.error("Error occurred while initializing user store.", e);
@ -311,4 +288,82 @@ public class OAuthExtUtils {
return trimmedName.substring(START_INDEX, trimmedName.lastIndexOf('@')); return trimmedName.substring(START_INDEX, trimmedName.lastIndexOf('@'));
} }
public static boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) {
boolean isScopesSet = ScopesIssuer.getInstance().setScopes(tokReqMsgCtx);
if (isScopesSet) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
tokReqMsgCtx.getAuthorizedUser().getTenantDomain(), true);
String username = tokReqMsgCtx.getAuthorizedUser().getUserName();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username);
try {
DeviceRequestDTO deviceRequestDTO = null;
RequestParameter parameters[] = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getRequestParameters();
for (RequestParameter parameter : parameters) {
if (OAuthConstants.DEFAULT_DEVICE_ASSERTION.equals(parameter.getKey())) {
String deviceJson = parameter.getValue()[0];
Gson gson = new Gson();
deviceRequestDTO = gson.fromJson(new String(Base64.decodeBase64(deviceJson)),
DeviceRequestDTO.class);
}
}
if (deviceRequestDTO != null) {
String requestScopes = deviceRequestDTO.getScope();
String scopeNames[] = requestScopes.split(" ");
for (String scopeName : scopeNames) {
List<DeviceIdentifier> deviceIdentifiers = deviceRequestDTO.getDeviceIdentifiers();
DeviceAuthorizationResult deviceAuthorizationResult = OAuthExtensionsDataHolder.getInstance()
.getDeviceAccessAuthorizationService()
.isUserAuthorized(deviceIdentifiers, username, getPermissions(scopeName));
if (deviceAuthorizationResult != null &&
deviceAuthorizationResult.getAuthorizedDevices() != null) {
String scopes[] = tokReqMsgCtx.getScope();
String authorizedScopes[] = new String[scopes.length + deviceAuthorizationResult
.getAuthorizedDevices().size()];
int scopeIndex = 0;
for (String scope : scopes) {
authorizedScopes[scopeIndex] = scope;
scopeIndex++;
}
for (DeviceIdentifier deviceIdentifier : deviceAuthorizationResult.getAuthorizedDevices()) {
authorizedScopes[scopeIndex] =
DEFAULT_SCOPE_TAG + ":" + deviceIdentifier.getType() + ":" +
deviceIdentifier.getId() + ":" + scopeName;
scopeIndex++;
}
tokReqMsgCtx.setScope(authorizedScopes);
}
}
}
} catch (DeviceAccessAuthorizationException e) {
log.error("Error occurred while checking authorization for the user " + username, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
return isScopesSet;
}
/**
* retrieve the permission related to given scope.
* @param scopeName requested scope action
* @return set of permission associated with the given scope.
*/
private static String[] getPermissions(String scopeName) {
return DeviceMgtScopesConfig.getInstance().getDeviceMgtScopePermissionMap().get(scopeName);
}
public static Document convertToDocument(File file) throws DeviceMgtScopesConfigurationFailedException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);
} catch (Exception e) {
throw new DeviceMgtScopesConfigurationFailedException("Error occurred while parsing file, while converting " +
"to a org.w3c.dom.Document", e);
}
}
} }

@ -0,0 +1,90 @@
package org.wso2.carbon.device.mgt.oauth.extensions.config;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for Action complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType name="Action">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="Permissions" type="{}Permissions"/>
* &lt;/sequence>
* &lt;attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Action", propOrder = {
"permissions"
})
public class Action {
@XmlElement(name = "Permissions", required = true)
protected Permissions permissions;
@XmlAttribute(name = "name")
protected String name;
/**
* Gets the value of the permissions property.
*
* @return
* possible object is
* {@link Permissions }
*
*/
public Permissions getPermissions() {
return permissions;
}
/**
* Sets the value of the permissions property.
*
* @param value
* allowed object is
* {@link Permissions }
*
*/
public void setPermissions(Permissions value) {
this.permissions = value;
}
/**
* Gets the value of the name property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getName() {
return name;
}
/**
* Sets the value of the name property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setName(String value) {
this.name = value;
}
}

@ -0,0 +1,67 @@
package org.wso2.carbon.device.mgt.oauth.extensions.config;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for DeviceMgtScopes complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType name="DeviceMgtScopes">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="Action" type="{}Action" maxOccurs="unbounded" minOccurs="0"/>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlRootElement(name = "DeviceMgtScopes")
public class DeviceMgtScopes {
@XmlElement(name = "Action")
protected List<Action> action;
/**
* Gets the value of the action property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the action property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getAction().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Action }
*
*
*/
public List<Action> getAction() {
if (action == null) {
action = new ArrayList<Action>();
}
return this.action;
}
}

@ -0,0 +1,67 @@
package org.wso2.carbon.device.mgt.oauth.extensions.config;
import org.w3c.dom.Document;
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthExtUtils;
import org.wso2.carbon.utils.CarbonUtils;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* This class represents the configuration that are needed for scopes to permission map.
*/
public class DeviceMgtScopesConfig {
private static DeviceMgtScopesConfig config = new DeviceMgtScopesConfig();
private static Map<String, String[]> actionPermissionMap = new HashMap<>();
private static final String DEVICE_MGT_SCOPES_CONFIG_PATH =
CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "device-mgt-scopes.xml";
private DeviceMgtScopesConfig() {
}
public static DeviceMgtScopesConfig getInstance() {
return config;
}
public static void init() throws DeviceMgtScopesConfigurationFailedException {
try {
File deviceMgtConfig = new File(DEVICE_MGT_SCOPES_CONFIG_PATH);
Document doc = OAuthExtUtils.convertToDocument(deviceMgtConfig);
/* Un-marshaling DeviceMGtScope configuration */
JAXBContext ctx = JAXBContext.newInstance(DeviceMgtScopes.class);
Unmarshaller unmarshaller = ctx.createUnmarshaller();
//unmarshaller.setSchema(getSchema());
DeviceMgtScopes deviceMgtScopes = (DeviceMgtScopes) unmarshaller.unmarshal(doc);
if (deviceMgtScopes != null) {
for (Action action : deviceMgtScopes.getAction()) {
Permissions permissions = action.getPermissions();
if (permissions != null) {
String permission[] = new String[permissions.getPermission().size()];
int i = 0;
for (String perm : permissions.getPermission()) {
permission[i] = perm;
i++;
}
actionPermissionMap.put(action.getName(), permission);
}
}
}
} catch (JAXBException e) {
throw new DeviceMgtScopesConfigurationFailedException("Error occurred while un-marshalling Device Scope" +
" Config", e);
}
}
public Map<String, String[]> getDeviceMgtScopePermissionMap() {
return actionPermissionMap;
}
}

@ -0,0 +1,44 @@
/*
* 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.oauth.extensions.config;
public class DeviceMgtScopesConfigurationFailedException extends Exception {
private static final long serialVersionUID = -3151279312929070398L;
public DeviceMgtScopesConfigurationFailedException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public DeviceMgtScopesConfigurationFailedException(String message, Throwable cause) {
super(message, cause);
}
public DeviceMgtScopesConfigurationFailedException(String msg) {
super(msg);
}
public DeviceMgtScopesConfigurationFailedException() {
super();
}
public DeviceMgtScopesConfigurationFailedException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,78 @@
package org.wso2.carbon.device.mgt.oauth.extensions.config;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for Permissions complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType name="Permissions">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="Permission" maxOccurs="unbounded" minOccurs="0">
* &lt;simpleType>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
* &lt;enumeration value="/permission/device-mgt/user/groups/device_operation"/>
* &lt;enumeration value="/permission/device-mgt/admin/groups"/>
* &lt;enumeration value="/permission/device-mgt/user/groups"/>
* &lt;enumeration value="/permission/device-mgt/user/groups/device_monitor"/>
* &lt;/restriction>
* &lt;/simpleType>
* &lt;/element>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Permissions", propOrder = {
"permission"
})
public class Permissions {
@XmlElement(name = "Permission")
protected List<String> permission;
/**
* Gets the value of the permission property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the permission property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getPermission().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link String }
*
*
*/
public List<String> getPermission() {
if (permission == null) {
permission = new ArrayList<String>();
}
return this.permission;
}
}

@ -5,10 +5,10 @@ import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.grant.jwt.JWTBearerGrantHandler; import org.wso2.carbon.identity.oauth2.grant.jwt.JWTBearerGrantHandler;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext; import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
public class ExtendedJWTBearerGrantHandler extends JWTBearerGrantHandler { public class ExtendedDeviceMgtJWTBearerGrantHandler extends JWTBearerGrantHandler {
@Override @Override
public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception { public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception {
return OAuthExtUtils.setScopes(tokReqMsgCtx); return OAuthExtUtils.validateScope(tokReqMsgCtx);
} }
} }

@ -0,0 +1,59 @@
/*
* 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.oauth.extensions.handlers.grant;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.keymgt.handlers.ExtendedPasswordGrantHandler;
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthConstants;
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthExtUtils;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.model.RequestParameter;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
@SuppressWarnings("unused")
public class ExtendedDeviceMgtPasswordGrantHandler extends ExtendedPasswordGrantHandler {
private static Log log = LogFactory.getLog(ExtendedDeviceMgtPasswordGrantHandler.class);
@Override
public boolean validateGrant(OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception {
RequestParameter parameters[] = tokReqMsgCtx.getOauth2AccessTokenReqDTO().getRequestParameters();
for (RequestParameter parameter : parameters) {
switch (parameter.getKey()) {
case OAuthConstants.DEFAULT_USERNAME_IDENTIFIER:
String username = parameter.getValue()[0];
tokReqMsgCtx.getOauth2AccessTokenReqDTO().setResourceOwnerUsername(username);
break;
case OAuthConstants.DEFAULT_PASSWORD_IDENTIFIER:
String password = parameter.getValue()[0];
tokReqMsgCtx.getOauth2AccessTokenReqDTO().setResourceOwnerPassword(password);
break;
}
}
return super.validateGrant(tokReqMsgCtx);
}
@Override
public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) {
return OAuthExtUtils.validateScope(tokReqMsgCtx);
}
}

@ -1,328 +0,0 @@
/*
* 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.oauth.extensions.handlers.grant;
import org.apache.axiom.om.OMElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthExtUtils;
import org.wso2.carbon.device.mgt.oauth.extensions.internal.OAuthExtensionsDataHolder;
import org.wso2.carbon.identity.application.common.cache.BaseCache;
import org.wso2.carbon.identity.core.util.IdentityConfigParser;
import org.wso2.carbon.identity.core.util.IdentityCoreConstants;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.oauth.common.OAuthConstants;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.ResponseHeader;
import org.wso2.carbon.identity.oauth2.dto.OAuth2AccessTokenReqDTO;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.token.handlers.grant.PasswordGrantHandler;
import org.wso2.carbon.user.api.Claim;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.user.core.UserRealm;
import org.wso2.carbon.user.core.config.RealmConfiguration;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.user.core.util.UserCoreUtil;
import javax.xml.namespace.QName;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("unused")
public class ExtendedPasswordGrantHandler extends PasswordGrantHandler {
private static Log log = LogFactory.getLog(ExtendedPasswordGrantHandler.class);
private static final String CONFIG_ELEM_OAUTH = "OAuth";
// Claims that are set as response headers of access token response
private static final String REQUIRED_CLAIM_URIS = "RequiredRespHeaderClaimUris";
private BaseCache<String, Claim[]> userClaimsCache;
// Primary/Secondary Login configuration
private static final String CLAIM_URI = "ClaimUri";
private static final String LOGIN_CONFIG = "LoginConfig";
private static final String USERID_LOGIN = "UserIdLogin";
private static final String EMAIL_LOGIN = "EmailLogin";
private static final String PRIMARY_LOGIN = "primary";
private Map<String, Map<String, String>> loginConfiguration = new ConcurrentHashMap<>();
private List<String> requiredHeaderClaimUris = new ArrayList<>();
public void init() throws IdentityOAuth2Exception {
super.init();
IdentityConfigParser configParser;
configParser = IdentityConfigParser.getInstance();
OMElement oauthElem = configParser.getConfigElement(CONFIG_ELEM_OAUTH);
// Get the required claim uris that needs to be included in the response.
parseRequiredHeaderClaimUris(oauthElem.getFirstChildWithName(getQNameWithIdentityNS(REQUIRED_CLAIM_URIS)));
// read login config
parseLoginConfig(oauthElem);
userClaimsCache = new BaseCache<>("UserClaimsCache");
if (log.isDebugEnabled()) {
log.debug("Successfully created UserClaimsCache under " + OAuthConstants.OAUTH_CACHE_MANAGER);
}
}
@Override
public boolean validateGrant(OAuthTokenReqMessageContext tokReqMsgCtx)
throws IdentityOAuth2Exception {
OAuth2AccessTokenReqDTO oAuth2AccessTokenReqDTO = tokReqMsgCtx.getOauth2AccessTokenReqDTO();
String username = oAuth2AccessTokenReqDTO.getResourceOwnerUsername();
String loginUserName = getLoginUserName(username);
tokReqMsgCtx.getOauth2AccessTokenReqDTO().setResourceOwnerUsername(loginUserName);
boolean isValidated = super.validateGrant(tokReqMsgCtx);
if (isValidated) {
int tenantId;
tenantId = IdentityTenantUtil.getTenantIdOfUser(username);
RealmService realmService = OAuthExtensionsDataHolder.getInstance().getRealmService();
UserStoreManager userStoreManager;
try {
userStoreManager = realmService.getTenantUserRealm(tenantId).getUserStoreManager();
} catch (UserStoreException e) {
log.error("Error when getting the tenant's UserStoreManager", e);
return false;
}
List<ResponseHeader> respHeaders = new ArrayList<>();
if (oAuth2AccessTokenReqDTO.getResourceOwnerUsername() != null) {
try {
if (requiredHeaderClaimUris != null && !requiredHeaderClaimUris.isEmpty()) {
// Get user's claim values from the default profile.
String userStoreDomain = tokReqMsgCtx.getAuthorizedUser().getUserStoreDomain();
String endUsernameWithDomain = UserCoreUtil.
addDomainToName(oAuth2AccessTokenReqDTO.getResourceOwnerUsername(), userStoreDomain);
Claim[] mapClaimValues = getUserClaimValues(endUsernameWithDomain, userStoreManager);
if (mapClaimValues != null && mapClaimValues.length > 0) {
ResponseHeader header;
for (String claimUri : requiredHeaderClaimUris) {
for (Claim claim : mapClaimValues) {
if (claimUri.equals(claim.getClaimUri())) {
header = new ResponseHeader();
header.setKey(claim.getDisplayTag());
header.setValue(claim.getValue());
respHeaders.add(header);
break;
}
}
}
} else if (log.isDebugEnabled()) {
log.debug("No claim values for user : " + endUsernameWithDomain);
}
}
} catch (Exception e) {
throw new IdentityOAuth2Exception("Error occurred while retrieving user claims", e);
}
}
tokReqMsgCtx.addProperty("RESPONSE_HEADERS", respHeaders.toArray(new ResponseHeader[respHeaders.size()]));
}
return isValidated;
}
@Override
public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) {
return OAuthExtUtils.setScopes(tokReqMsgCtx);
}
private String getLoginUserName(String userID) {
String loginUserName = userID;
if (isSecondaryLogin(userID)) {
loginUserName = getPrimaryFromSecondary(userID);
}
return loginUserName;
}
/**
* Identify whether the logged in user used his Primary Login name or
* Secondary login name
*
* @param userId - The username used to login.
* @return <code>true</code> if secondary login name is used,
* <code>false</code> if primary login name has been used
*/
private boolean isSecondaryLogin(String userId) {
if (loginConfiguration.get(EMAIL_LOGIN) != null) {
Map<String, String> emailConf = loginConfiguration.get(EMAIL_LOGIN);
if ("true".equalsIgnoreCase(emailConf.get(PRIMARY_LOGIN))) {
return !isUserLoggedInEmail(userId);
} else if ("false".equalsIgnoreCase(emailConf.get(PRIMARY_LOGIN))) {
return isUserLoggedInEmail(userId);
}
} else if (loginConfiguration.get(USERID_LOGIN) != null) {
Map<String, String> userIdConf = loginConfiguration.get(USERID_LOGIN);
if ("true".equalsIgnoreCase(userIdConf.get(PRIMARY_LOGIN))) {
return isUserLoggedInEmail(userId);
} else if ("false".equalsIgnoreCase(userIdConf.get(PRIMARY_LOGIN))) {
return !isUserLoggedInEmail(userId);
}
}
return false;
}
/**
* Identify whether the logged in user used his ordinal username or email
*
* @param userId - username used to login.
* @return - <code>true</code> if userId contains '@'. <code>false</code> otherwise
*/
private boolean isUserLoggedInEmail(String userId) {
return userId.contains("@");
}
/**
* Get the primaryLogin name using secondary login name. Primary secondary
* Configuration is provided in the identitiy.xml. In the userstore, it is
* users responsibility TO MAINTAIN THE SECONDARY LOGIN NAME AS UNIQUE for
* each and every users. If it is not unique, we will pick the very first
* entry from the userlist.
*
* @param login - username used to login.
* @return -
*/
private String getPrimaryFromSecondary(String login) {
String claimURI, username = null;
if (isUserLoggedInEmail(login)) {
Map<String, String> emailConf = loginConfiguration.get(EMAIL_LOGIN);
claimURI = emailConf.get(CLAIM_URI);
} else {
Map<String, String> userIdConf = loginConfiguration.get(USERID_LOGIN);
claimURI = userIdConf.get(CLAIM_URI);
}
try {
RealmService realmSvc = OAuthExtensionsDataHolder.getInstance().getRealmService();
RealmConfiguration config = new RealmConfiguration();
UserRealm realm = realmSvc.getUserRealm(config);
org.wso2.carbon.user.core.UserStoreManager storeManager = realm.getUserStoreManager();
String[] user = storeManager.getUserList(claimURI, login, null);
if (user.length > 0) {
username = user[0];
}
} catch (UserStoreException e) {
log.error("Error while retrieving the primaryLogin name using secondary login name : " + login, e);
}
return username;
}
private Claim[] getUserClaimValues(String authorizedUser, UserStoreManager userStoreManager)
throws
UserStoreException {
Claim[] userClaims = userClaimsCache.getValueFromCache(authorizedUser);
if (userClaims != null) {
return userClaims;
} else {
if (log.isDebugEnabled()) {
log.debug("Cache miss for user claims. Username :" + authorizedUser);
}
userClaims = userStoreManager.getUserClaimValues(
authorizedUser, null);
userClaimsCache.addToCache(authorizedUser, userClaims);
return userClaims;
}
}
/**
* Read the required claim configuration from identity.xml
*/
private void parseRequiredHeaderClaimUris(OMElement requiredClaimUrisElem) {
if (requiredClaimUrisElem == null) {
return;
}
Iterator claimUris = requiredClaimUrisElem.getChildrenWithLocalName(CLAIM_URI);
if (claimUris != null) {
while (claimUris.hasNext()) {
OMElement claimUri = (OMElement) claimUris.next();
if (claimUri != null) {
requiredHeaderClaimUris.add(claimUri.getText());
}
}
}
}
/**
* Read the primary/secondary login configuration
* <OAuth>
* ....
* <LoginConfig>
* <UserIdLogin primary="true">
* <ClaimUri></ClaimUri>
* </UserIdLogin>
* <EmailLogin primary="false">
* <ClaimUri>http://wso2.org/claims/emailaddress</ClaimUri>
* </EmailLogin>
* </LoginConfig>
* .....
* </OAuth>
*
* @param oauthConfigElem - The '<LoginConfig>' xml configuration element in the api-manager.xml
*/
private void parseLoginConfig(OMElement oauthConfigElem) {
OMElement loginConfigElem = oauthConfigElem.getFirstChildWithName(getQNameWithIdentityNS(LOGIN_CONFIG));
if (loginConfigElem != null) {
if (log.isDebugEnabled()) {
log.debug("Login configuration is set ");
}
// Primary/Secondary supported login mechanisms
OMElement emailConfigElem = loginConfigElem.getFirstChildWithName(getQNameWithIdentityNS(EMAIL_LOGIN));
OMElement userIdConfigElem = loginConfigElem.getFirstChildWithName(getQNameWithIdentityNS(USERID_LOGIN));
Map<String, String> emailConf = new HashMap<String, String>(2);
emailConf.put(PRIMARY_LOGIN,
emailConfigElem.getAttributeValue(new QName(PRIMARY_LOGIN)));
emailConf.put(CLAIM_URI,
emailConfigElem.getFirstChildWithName(getQNameWithIdentityNS(CLAIM_URI))
.getText());
Map<String, String> userIdConf = new HashMap<String, String>(2);
userIdConf.put(PRIMARY_LOGIN,
userIdConfigElem.getAttributeValue(new QName(PRIMARY_LOGIN)));
userIdConf.put(CLAIM_URI,
userIdConfigElem.getFirstChildWithName(getQNameWithIdentityNS(CLAIM_URI))
.getText());
loginConfiguration.put(EMAIL_LOGIN, emailConf);
loginConfiguration.put(USERID_LOGIN, userIdConf);
}
}
private QName getQNameWithIdentityNS(String localPart) {
return new QName(IdentityCoreConstants.IDENTITY_DEFAULT_NAMESPACE, localPart);
}
}

@ -24,8 +24,12 @@ import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.APIManagerConfiguration; import org.wso2.carbon.apimgt.impl.APIManagerConfiguration;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagerService; import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagerService;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.oauth.extensions.config.DeviceMgtScopesConfig;
import org.wso2.carbon.device.mgt.oauth.extensions.config.DeviceMgtScopesConfigurationFailedException;
import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService;
import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.CarbonUtils;
@ -54,12 +58,12 @@ import java.util.List;
* policy="dynamic" * policy="dynamic"
* bind="setPermissionManagerService" * bind="setPermissionManagerService"
* unbind="unsetPermissionManagerService" * unbind="unsetPermissionManagerService"
* @scr.reference name="org.wso2.carbon.device.manager" * @scr.reference name="org.wso2.carbon.device.authorization"
* interface="org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService" * interface="org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService"
* cardinality="1..1" * cardinality="1..1"
* policy="dynamic" * policy="dynamic"
* bind="setDeviceManagementService" * bind="setDeviceAccessAuthorizationService"
* unbind="unsetDeviceManagementService" * unbind="unsetDeviceAccessAuthorizationService"
*/ */
public class OAuthExtensionServiceComponent { public class OAuthExtensionServiceComponent {
@ -67,8 +71,6 @@ public class OAuthExtensionServiceComponent {
private static final String REPOSITORY = "repository"; private static final String REPOSITORY = "repository";
private static final String CONFIGURATION = "conf"; private static final String CONFIGURATION = "conf";
private static final String APIM_CONF_FILE = "api-manager.xml"; private static final String APIM_CONF_FILE = "api-manager.xml";
private static final String API_KEY_MANGER_DEVICE_SCOPE = "APIKeyValidator.DeviceScope";
private static final String CDMF_DEVICE_SCOPE_PREFIX = "cdmf_";
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -77,6 +79,8 @@ public class OAuthExtensionServiceComponent {
log.debug("Starting OAuthExtensionBundle"); log.debug("Starting OAuthExtensionBundle");
} }
try { try {
DeviceMgtScopesConfig.init();
APIManagerConfiguration configuration = new APIManagerConfiguration(); APIManagerConfiguration configuration = new APIManagerConfiguration();
String filePath = new StringBuilder(). String filePath = new StringBuilder().
append(CarbonUtils.getCarbonHome()). append(CarbonUtils.getCarbonHome()).
@ -102,18 +106,10 @@ public class OAuthExtensionServiceComponent {
} }
OAuthExtensionsDataHolder.getInstance().setWhitelistedScopes(whiteList); OAuthExtensionsDataHolder.getInstance().setWhitelistedScopes(whiteList);
// Read device scope(Specific to CDMF) from Configuration.
String deviceScope = configuration.getFirstProperty(API_KEY_MANGER_DEVICE_SCOPE);
if (deviceScope == null) {
deviceScope = CDMF_DEVICE_SCOPE_PREFIX;
}
OAuthExtensionsDataHolder.getInstance().setDeviceScope(deviceScope);
} catch (APIManagementException e) { } catch (APIManagementException e) {
log.error("Error occurred while loading APIM configurations", e); log.error("Error occurred while loading DeviceMgtConfig configurations", e);
} catch (DeviceMgtScopesConfigurationFailedException e) {
log.error("Failed to initialize device scope configuration.", e);
} }
} }
@ -198,24 +194,24 @@ public class OAuthExtensionServiceComponent {
/** /**
* Set DeviceManagementProviderService * Set DeviceManagementProviderService
* @param deviceManagerService An instance of PermissionManagerService * @param deviceAccessAuthorizationService An instance of deviceAccessAuthorizationService
*/ */
protected void setDeviceManagementService(DeviceManagementProviderService deviceManagerService) { protected void setDeviceAccessAuthorizationService(DeviceAccessAuthorizationService deviceAccessAuthorizationService) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Setting Device Management Service"); log.debug("Setting Device Management Service");
} }
OAuthExtensionsDataHolder.getInstance().setDeviceManagementService(deviceManagerService); OAuthExtensionsDataHolder.getInstance().setDeviceAccessAuthorizationService(deviceAccessAuthorizationService);
} }
/** /**
* unset DeviceManagementProviderService * unset DeviceManagementProviderService
* @param deviceManagementService An instance of PermissionManagerService * @param deviceAccessAuthorizationService An instance of deviceAccessAuthorizationService
*/ */
protected void unsetDeviceManagementService(DeviceManagementProviderService deviceManagementService) { protected void unsetDeviceAccessAuthorizationService(DeviceAccessAuthorizationService deviceAccessAuthorizationService) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Removing Device Management Service"); log.debug("Removing Device Management Service");
} }
OAuthExtensionsDataHolder.getInstance().setDeviceManagementService(null); OAuthExtensionsDataHolder.getInstance().setDeviceAccessAuthorizationService(null);
} }
} }

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.oauth.extensions.internal; package org.wso2.carbon.device.mgt.oauth.extensions.internal;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagerService; import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagerService;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService;
@ -35,7 +36,7 @@ public class OAuthExtensionsDataHolder {
private PermissionManagerService permissionManagerService; private PermissionManagerService permissionManagerService;
private List<String> whitelistedScopes; private List<String> whitelistedScopes;
private String deviceScope; private String deviceScope;
private DeviceManagementProviderService deviceManagementService; private DeviceAccessAuthorizationService deviceAccessAuthorizationService;
private static OAuthExtensionsDataHolder thisInstance = new OAuthExtensionsDataHolder(); private static OAuthExtensionsDataHolder thisInstance = new OAuthExtensionsDataHolder();
@ -87,19 +88,15 @@ public class OAuthExtensionsDataHolder {
this.whitelistedScopes = whitelistedScopes; this.whitelistedScopes = whitelistedScopes;
} }
public void setDeviceScope(String deviceScope) {
this.deviceScope = deviceScope;
}
public String getDeviceScope() { public String getDeviceScope() {
return deviceScope; return deviceScope;
} }
public DeviceManagementProviderService getDeviceManagementService() { public DeviceAccessAuthorizationService getDeviceAccessAuthorizationService() {
return deviceManagementService; return deviceAccessAuthorizationService;
} }
public void setDeviceManagementService(DeviceManagementProviderService deviceManagementService) { public void setDeviceAccessAuthorizationService(DeviceAccessAuthorizationService deviceAccessAuthorizationService) {
this.deviceManagementService = deviceManagementService; this.deviceAccessAuthorizationService = deviceAccessAuthorizationService;
} }
} }

@ -0,0 +1,38 @@
/*
* 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.oauth.extensions.validators;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.validators.AbstractValidator;
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthConstants;
import javax.servlet.http.HttpServletRequest;
/**
* Grant validator for JSON Web Tokens
* For JWT Grant to be valid the required parameters are
* grant_type and assertion
*/
public class ExtendedDeviceJWTGrantValidator extends AbstractValidator<HttpServletRequest> {
public ExtendedDeviceJWTGrantValidator() {
requiredParams.add(OAuth.OAUTH_GRANT_TYPE);
requiredParams.add(OAuth.OAUTH_ASSERTION);
}
}

@ -0,0 +1,37 @@
/*
* 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.oauth.extensions.validators;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.validators.AbstractValidator;
import org.wso2.carbon.device.mgt.oauth.extensions.OAuthConstants;
import javax.servlet.http.HttpServletRequest;
/**
* Grant validator for Device Object with Password Grant type
*/
public class ExtendedDevicePasswordGrantValidator extends AbstractValidator<HttpServletRequest> {
public ExtendedDevicePasswordGrantValidator() {
requiredParams.add(OAuth.OAUTH_USERNAME);
requiredParams.add(OAuth.OAUTH_PASSWORD);
requiredParams.add(OAuthConstants.DEFAULT_DEVICE_ASSERTION);
}
}

@ -44,6 +44,7 @@ import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* this class represents an implementation of Token Client which is based on JWT * this class represents an implementation of Token Client which is based on JWT
@ -63,14 +64,10 @@ public class JWTClient {
this.isDefaultJWTClient = isDefaultJWTClient; this.isDefaultJWTClient = isDefaultJWTClient;
} }
/**
* {@inheritDoc}
*/
public AccessTokenInfo getAccessToken(String consumerKey, String consumerSecret, String username, String scopes) public AccessTokenInfo getAccessToken(String consumerKey, String consumerSecret, String username, String scopes)
throws JWTClientException { throws JWTClientException {
List<NameValuePair> params = new ArrayList<>(); List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair(JWTConstants.GRANT_TYPE_PARAM_NAME, JWTConstants.JWT_GRANT_TYPE)); params.add(new BasicNameValuePair(JWTConstants.GRANT_TYPE_PARAM_NAME, jwtConfig.getJwtGrantType()));
String assertion = JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient); String assertion = JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient);
if (assertion == null) { if (assertion == null) {
throw new JWTClientException("JWT is not configured properly for user : " + username); throw new JWTClientException("JWT is not configured properly for user : " + username);
@ -80,9 +77,26 @@ public class JWTClient {
return getTokenInfo(params, consumerKey, consumerSecret); return getTokenInfo(params, consumerKey, consumerSecret);
} }
/** public AccessTokenInfo getAccessToken(String consumerKey, String consumerSecret, String username, String scopes,
* {@inheritDoc} Map<String, String> paramsMap)
*/ throws JWTClientException {
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair(JWTConstants.GRANT_TYPE_PARAM_NAME, jwtConfig.getJwtGrantType()));
String assertion = JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient);
if (assertion == null) {
throw new JWTClientException("JWT is not configured properly for user : " + username);
}
params.add(new BasicNameValuePair(JWTConstants.JWT_PARAM_NAME, assertion));
params.add(new BasicNameValuePair(JWTConstants.SCOPE_PARAM_NAME, scopes));
if (paramsMap != null) {
for (String key : paramsMap.keySet()) {
params.add(new BasicNameValuePair(key, paramsMap.get(key)));
}
}
return getTokenInfo(params, consumerKey, consumerSecret);
}
public AccessTokenInfo getAccessTokenFromRefreshToken(String refreshToken, String username, String scopes, public AccessTokenInfo getAccessTokenFromRefreshToken(String refreshToken, String username, String scopes,
String consumerKey, String consumerSecret) String consumerKey, String consumerSecret)
throws JWTClientException { throws JWTClientException {

@ -1,6 +1,7 @@
package org.wso2.carbon.identity.jwt.client.extension.dto; package org.wso2.carbon.identity.jwt.client.extension.dto;
import org.wso2.carbon.core.util.Utils; import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.identity.jwt.client.extension.constant.JWTConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -20,6 +21,7 @@ public class JWTConfig {
private static final String JKS_PASSWORD ="KeyStorePassword"; private static final String JKS_PASSWORD ="KeyStorePassword";
private static final String JKA_PRIVATE_KEY_PASSWORD = "PrivateKeyPassword"; private static final String JKA_PRIVATE_KEY_PASSWORD = "PrivateKeyPassword";
private static final String TOKEN_ENDPOINT = "TokenEndpoint"; private static final String TOKEN_ENDPOINT = "TokenEndpoint";
private static final String JWT_GRANT_TYPE_NAME = "GrantType";
/** /**
* issuer of the JWT * issuer of the JWT
@ -69,6 +71,11 @@ public class JWTConfig {
private String privateKeyAlias; private String privateKeyAlias;
private String privateKeyPassword; private String privateKeyPassword;
/**
* Jwt Grant Type Name
*/
private String jwtGrantType;
/** /**
* @param properties load the config from the properties file. * @param properties load the config from the properties file.
*/ */
@ -89,6 +96,8 @@ public class JWTConfig {
privateKeyAlias = properties.getProperty(JKS_PRIVATE_KEY_ALIAS); privateKeyAlias = properties.getProperty(JKS_PRIVATE_KEY_ALIAS);
privateKeyPassword = properties.getProperty(JKA_PRIVATE_KEY_PASSWORD); privateKeyPassword = properties.getProperty(JKA_PRIVATE_KEY_PASSWORD);
tokenEndpoint = properties.getProperty(TOKEN_ENDPOINT, ""); tokenEndpoint = properties.getProperty(TOKEN_ENDPOINT, "");
jwtGrantType = properties.getProperty(JWT_GRANT_TYPE_NAME, JWTConstants.JWT_GRANT_TYPE);
} }
private static List<String> getAudience(String audience){ private static List<String> getAudience(String audience){
@ -146,4 +155,8 @@ public class JWTConfig {
public String getTokenEndpoint() { public String getTokenEndpoint() {
return Utils.replaceSystemProperty(tokenEndpoint); return Utils.replaceSystemProperty(tokenEndpoint);
} }
public String getJwtGrantType() {
return jwtGrantType;
}
} }

@ -0,0 +1,19 @@
#
# 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.
#
custom = true

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ 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.
-->
<!--This holds the scopes that are allowed by the device-mgt, The user require below permission to get the required scope-->
<!--These scopes are assigned after validating with device-mgt specific grant types-->
<DeviceMgtScopes>
<Action name="mqtt-publisher">
<Permissions>
<Permission>/permission/device-mgt/user/groups/device_operation</Permission>
<Permission>/permission/device-mgt/admin/groups</Permission>
<Permission>/permission/device-mgt/user/groups</Permission>
</Permissions>
</Action>
<Action name="mqtt-subscriber">
<Permissions>
<Permission>/permission/device-mgt/user/groups/device_monitor</Permission>
<Permission>/permission/device-mgt/admin/groups</Permission>
<Permission>/permission/device-mgt/user/groups</Permission>
</Permissions>
</Action>
<Action name="stats">
<Permissions>
<Permission>/permission/device-mgt/user/groups/device_monitor</Permission>
<Permission>/permission/device-mgt/admin/groups</Permission>
<Permission>/permission/device-mgt/user/groups</Permission>
</Permissions>
</Action>
<Action name="operation">
<Permissions>
<Permission>/permission/device-mgt/user/groups/device_operation</Permission>
<Permission>/permission/device-mgt/admin/groups</Permission>
<Permission>/permission/device-mgt/user/groups</Permission>
</Permissions>
</Action>
</DeviceMgtScopes>

@ -0,0 +1,2 @@
instructions.configure = \
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.oauth.extensions_${feature.version}/device-mgt-scopes.xml,target:${installFolder}/../../conf/etc/device-mgt-scopes.xml,overwrite:true);\

@ -780,6 +780,11 @@
<artifactId>org.wso2.carbon.apimgt.keymgt.client</artifactId> <artifactId>org.wso2.carbon.apimgt.keymgt.client</artifactId>
<version>${carbon.api.mgt.version}</version> <version>${carbon.api.mgt.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.apimgt</groupId>
<artifactId>org.wso2.carbon.apimgt.keymgt</artifactId>
<version>${carbon.api.mgt.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.wso2.carbon.apimgt</groupId> <groupId>org.wso2.carbon.apimgt</groupId>
<artifactId>org.wso2.carbon.apimgt.impl</artifactId> <artifactId>org.wso2.carbon.apimgt.impl</artifactId>

Loading…
Cancel
Save