diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java index 4c2e57d8bda..27bbcc13eff 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/authorization/DeviceAccessAuthorizationServiceImpl.java @@ -202,18 +202,13 @@ public class DeviceAccessAuthorizationServiceImpl implements DeviceAccessAuthori throws DeviceAccessAuthorizationException { //Check for device ownership. If the user is the owner of the device we allow the access. try { - Device device = DeviceManagementDataHolder.getInstance().getDeviceManagementProvider(). - getDevice(deviceIdentifier); - EnrolmentInfo enrolmentInfo = device.getEnrolmentInfo(); - if (enrolmentInfo != null && username.equalsIgnoreCase(enrolmentInfo.getOwner())) { - return true; - } + return DeviceManagementDataHolder.getInstance().getDeviceManagementProvider(). + isEnrolled(deviceIdentifier, username); } catch (DeviceManagementException e) { throw new DeviceAccessAuthorizationException("Unable to authorize the access to device : " + deviceIdentifier.getId() + " for the user : " + username, e); } - return false; } private boolean isAdminUser(String username, int tenantId) throws UserStoreException { diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml index 74f6d9bcf35..0463e37cbb3 100644 --- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/pom.xml @@ -50,6 +50,10 @@ org.wso2.carbon.apimgt org.wso2.carbon.apimgt.impl + + org.wso2.carbon.apimgt + org.wso2.carbon.apimgt.keymgt + com.googlecode.json-simple.wso2 json-simple @@ -95,40 +99,41 @@ org.wso2.carbon.device.mgt.*, org.wso2.carbon.identity.application.common.model, org.wso2.carbon.identity.oauth.callback, - org.wso2.carbon.identity.oauth.common, org.wso2.carbon.identity.oauth2, org.wso2.carbon.identity.oauth2.model, org.wso2.carbon.identity.oauth2.validators, org.wso2.carbon.user.api, 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.json.simple, javax.cache, - javax.xml.namespace, - org.apache.axiom.om, org.wso2.carbon.apimgt.api, org.wso2.carbon.apimgt.impl, org.wso2.carbon.apimgt.impl.dao, org.wso2.carbon.apimgt.impl.utils, - org.wso2.carbon.identity.application.common.cache, org.wso2.carbon.identity.core.util, org.wso2.carbon.identity.oauth2.dto, org.wso2.carbon.identity.oauth2.token, - org.wso2.carbon.identity.oauth2.token.handlers.grant, - org.wso2.carbon.user.core, - org.wso2.carbon.user.core.config, - org.wso2.carbon.user.core.util, + org.apache.oltu.oauth2.common.validators, org.wso2.carbon.utils, org.wso2.carbon.context, org.wso2.carbon.identity.oauth.cache, org.wso2.carbon.identity.oauth.config, org.wso2.carbon.identity.oauth2.dao, org.wso2.carbon.utils.multitenancy, - org.wso2.carbon.base, 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 diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/DeviceRequestDTO.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/DeviceRequestDTO.java new file mode 100644 index 00000000000..75c4b35b3ab --- /dev/null +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/DeviceRequestDTO.java @@ -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 deviceIdentifiers; + private String scope; + + public List getDeviceIdentifiers() { + return deviceIdentifiers; + } + + public void setDeviceIdentifiers(List deviceIdentifiers) { + this.deviceIdentifiers = deviceIdentifiers; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } +} diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/OAuthConstants.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/OAuthConstants.java new file mode 100644 index 00000000000..eff890831de --- /dev/null +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/OAuthConstants.java @@ -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"; + +} diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/OAuthExtUtils.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/OAuthExtUtils.java index 97d7e5f5cf0..b52d94b657a 100644 --- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/OAuthExtUtils.java +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/OAuthExtUtils.java @@ -18,17 +18,25 @@ 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.LogFactory; +import org.w3c.dom.Document; import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.dao.ApiMgtDAO; 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.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.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.oauth2.model.RequestParameter; import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext; import org.wso2.carbon.user.api.TenantManager; 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 javax.cache.Caching; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -51,7 +62,8 @@ public class OAuthExtUtils { private static final String UI_EXECUTE = "ui.execute"; private static final String REST_API_SCOPE_CACHE = "REST_API_SCOPE_CACHE"; 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. * @@ -114,7 +126,7 @@ public class OAuthExtUtils { restAPIScopesOfCurrentTenant = APIUtil. 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 appScopes.putAll(restAPIScopesOfCurrentTenant); Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER) @@ -166,20 +178,6 @@ public class OAuthExtUtils { 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, * 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)) { 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) { log.error("Error occurred while initializing user store.", e); @@ -311,4 +288,82 @@ public class OAuthExtUtils { 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 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); + } + } + } diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/Action.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/Action.java new file mode 100644 index 00000000000..4f71e308014 --- /dev/null +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/Action.java @@ -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; + + +/** + *

Java class for Action complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="Action">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Permissions" type="{}Permissions"/>
+ *       </sequence>
+ *       <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@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; + } + +} diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/DeviceMgtScopes.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/DeviceMgtScopes.java new file mode 100644 index 00000000000..07a46b21304 --- /dev/null +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/DeviceMgtScopes.java @@ -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; + + +/** + *

Java class for DeviceMgtScopes complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="DeviceMgtScopes">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Action" type="{}Action" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlRootElement(name = "DeviceMgtScopes") +public class DeviceMgtScopes { + + @XmlElement(name = "Action") + protected List action; + + /** + * Gets the value of the action property. + * + *

+ * 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 set method for the action property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAction().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Action } + * + * + */ + public List getAction() { + if (action == null) { + action = new ArrayList(); + } + return this.action; + } + +} diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/DeviceMgtScopesConfig.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/DeviceMgtScopesConfig.java new file mode 100644 index 00000000000..9f8d05760b5 --- /dev/null +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/DeviceMgtScopesConfig.java @@ -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 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 getDeviceMgtScopePermissionMap() { + return actionPermissionMap; + } + +} diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/DeviceMgtScopesConfigurationFailedException.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/DeviceMgtScopesConfigurationFailedException.java new file mode 100644 index 00000000000..7a16382c18d --- /dev/null +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/DeviceMgtScopesConfigurationFailedException.java @@ -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); + } +} diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/Permissions.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/Permissions.java new file mode 100644 index 00000000000..dd20c772aff --- /dev/null +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/config/Permissions.java @@ -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; + + +/** + *

Java class for Permissions complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="Permissions">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Permission" maxOccurs="unbounded" minOccurs="0">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="/permission/device-mgt/user/groups/device_operation"/>
+ *               <enumeration value="/permission/device-mgt/admin/groups"/>
+ *               <enumeration value="/permission/device-mgt/user/groups"/>
+ *               <enumeration value="/permission/device-mgt/user/groups/device_monitor"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "Permissions", propOrder = { + "permission" +}) +public class Permissions { + + @XmlElement(name = "Permission") + protected List permission; + + /** + * Gets the value of the permission property. + * + *

+ * 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 set method for the permission property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getPermission().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getPermission() { + if (permission == null) { + permission = new ArrayList(); + } + return this.permission; + } + +} diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedJWTBearerGrantHandler.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedDeviceMgtJWTBearerGrantHandler.java similarity index 77% rename from components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedJWTBearerGrantHandler.java rename to components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedDeviceMgtJWTBearerGrantHandler.java index cb7fcdef190..b90ba6f7157 100644 --- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedJWTBearerGrantHandler.java +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedDeviceMgtJWTBearerGrantHandler.java @@ -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.token.OAuthTokenReqMessageContext; -public class ExtendedJWTBearerGrantHandler extends JWTBearerGrantHandler { +public class ExtendedDeviceMgtJWTBearerGrantHandler extends JWTBearerGrantHandler { @Override public boolean validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) throws IdentityOAuth2Exception { - return OAuthExtUtils.setScopes(tokReqMsgCtx); + return OAuthExtUtils.validateScope(tokReqMsgCtx); } } diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedDeviceMgtPasswordGrantHandler.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedDeviceMgtPasswordGrantHandler.java new file mode 100644 index 00000000000..04418991eed --- /dev/null +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedDeviceMgtPasswordGrantHandler.java @@ -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); + } + +} diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedPasswordGrantHandler.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedPasswordGrantHandler.java deleted file mode 100644 index d39ea69f0c2..00000000000 --- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedPasswordGrantHandler.java +++ /dev/null @@ -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 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> loginConfiguration = new ConcurrentHashMap<>(); - - private List 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 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 true if secondary login name is used, - * false if primary login name has been used - */ - private boolean isSecondaryLogin(String userId) { - - if (loginConfiguration.get(EMAIL_LOGIN) != null) { - Map 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 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 - true if userId contains '@'. false 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 emailConf = loginConfiguration.get(EMAIL_LOGIN); - claimURI = emailConf.get(CLAIM_URI); - } else { - Map 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 - * - * .... - * - * - * - * - * - * http://wso2.org/claims/emailaddress - * - * - * ..... - * - * - * @param oauthConfigElem - The '' 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 emailConf = new HashMap(2); - emailConf.put(PRIMARY_LOGIN, - emailConfigElem.getAttributeValue(new QName(PRIMARY_LOGIN))); - emailConf.put(CLAIM_URI, - emailConfigElem.getFirstChildWithName(getQNameWithIdentityNS(CLAIM_URI)) - .getText()); - - Map userIdConf = new HashMap(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); - } -} diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionServiceComponent.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionServiceComponent.java index 350de887a4d..8e483bd1a44 100644 --- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionServiceComponent.java +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionServiceComponent.java @@ -24,8 +24,12 @@ import org.osgi.service.component.ComponentContext; import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.impl.APIConstants; 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.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.user.core.service.RealmService; import org.wso2.carbon.utils.CarbonUtils; @@ -54,12 +58,12 @@ import java.util.List; * policy="dynamic" * bind="setPermissionManagerService" * unbind="unsetPermissionManagerService" - * @scr.reference name="org.wso2.carbon.device.manager" - * interface="org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService" + * @scr.reference name="org.wso2.carbon.device.authorization" + * interface="org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService" * cardinality="1..1" * policy="dynamic" - * bind="setDeviceManagementService" - * unbind="unsetDeviceManagementService" + * bind="setDeviceAccessAuthorizationService" + * unbind="unsetDeviceAccessAuthorizationService" */ public class OAuthExtensionServiceComponent { @@ -67,8 +71,6 @@ public class OAuthExtensionServiceComponent { private static final String REPOSITORY = "repository"; private static final String CONFIGURATION = "conf"; 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") @@ -77,6 +79,8 @@ public class OAuthExtensionServiceComponent { log.debug("Starting OAuthExtensionBundle"); } try { + DeviceMgtScopesConfig.init(); + APIManagerConfiguration configuration = new APIManagerConfiguration(); String filePath = new StringBuilder(). append(CarbonUtils.getCarbonHome()). @@ -102,18 +106,10 @@ public class OAuthExtensionServiceComponent { } 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) { - 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 - * @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()) { log.debug("Setting Device Management Service"); } - OAuthExtensionsDataHolder.getInstance().setDeviceManagementService(deviceManagerService); + OAuthExtensionsDataHolder.getInstance().setDeviceAccessAuthorizationService(deviceAccessAuthorizationService); } /** * 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()) { log.debug("Removing Device Management Service"); } - OAuthExtensionsDataHolder.getInstance().setDeviceManagementService(null); + OAuthExtensionsDataHolder.getInstance().setDeviceAccessAuthorizationService(null); } } diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionsDataHolder.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionsDataHolder.java index 2f052094d79..5e4d953fc4b 100644 --- a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionsDataHolder.java +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/internal/OAuthExtensionsDataHolder.java @@ -18,6 +18,7 @@ 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.core.service.DeviceManagementProviderService; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; @@ -35,7 +36,7 @@ public class OAuthExtensionsDataHolder { private PermissionManagerService permissionManagerService; private List whitelistedScopes; private String deviceScope; - private DeviceManagementProviderService deviceManagementService; + private DeviceAccessAuthorizationService deviceAccessAuthorizationService; private static OAuthExtensionsDataHolder thisInstance = new OAuthExtensionsDataHolder(); @@ -87,19 +88,15 @@ public class OAuthExtensionsDataHolder { this.whitelistedScopes = whitelistedScopes; } - public void setDeviceScope(String deviceScope) { - this.deviceScope = deviceScope; - } - public String getDeviceScope() { return deviceScope; } - public DeviceManagementProviderService getDeviceManagementService() { - return deviceManagementService; + public DeviceAccessAuthorizationService getDeviceAccessAuthorizationService() { + return deviceAccessAuthorizationService; } - public void setDeviceManagementService(DeviceManagementProviderService deviceManagementService) { - this.deviceManagementService = deviceManagementService; + public void setDeviceAccessAuthorizationService(DeviceAccessAuthorizationService deviceAccessAuthorizationService) { + this.deviceAccessAuthorizationService = deviceAccessAuthorizationService; } } diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedDeviceJWTGrantValidator.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedDeviceJWTGrantValidator.java new file mode 100644 index 00000000000..903c3997d46 --- /dev/null +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedDeviceJWTGrantValidator.java @@ -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 { + + public ExtendedDeviceJWTGrantValidator() { + requiredParams.add(OAuth.OAUTH_GRANT_TYPE); + requiredParams.add(OAuth.OAUTH_ASSERTION); + } +} \ No newline at end of file diff --git a/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedDevicePasswordGrantValidator.java b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedDevicePasswordGrantValidator.java new file mode 100644 index 00000000000..e22b211f5f1 --- /dev/null +++ b/components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/validators/ExtendedDevicePasswordGrantValidator.java @@ -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 { + + public ExtendedDevicePasswordGrantValidator() { + requiredParams.add(OAuth.OAUTH_USERNAME); + requiredParams.add(OAuth.OAUTH_PASSWORD); + requiredParams.add(OAuthConstants.DEFAULT_DEVICE_ASSERTION); + } +} \ No newline at end of file diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClient.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClient.java index b4081fa600c..55da4229b3b 100644 --- a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClient.java +++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClient.java @@ -44,6 +44,7 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * this class represents an implementation of Token Client which is based on JWT @@ -63,14 +64,10 @@ public class JWTClient { this.isDefaultJWTClient = isDefaultJWTClient; } - - /** - * {@inheritDoc} - */ public AccessTokenInfo getAccessToken(String consumerKey, String consumerSecret, String username, String scopes) throws JWTClientException { List 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); if (assertion == null) { throw new JWTClientException("JWT is not configured properly for user : " + username); @@ -80,9 +77,26 @@ public class JWTClient { return getTokenInfo(params, consumerKey, consumerSecret); } - /** - * {@inheritDoc} - */ + public AccessTokenInfo getAccessToken(String consumerKey, String consumerSecret, String username, String scopes, + Map paramsMap) + throws JWTClientException { + List 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, String consumerKey, String consumerSecret) throws JWTClientException { diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/dto/JWTConfig.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/dto/JWTConfig.java index 11ee9053ae6..67ebcb40990 100644 --- a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/dto/JWTConfig.java +++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/dto/JWTConfig.java @@ -1,6 +1,7 @@ package org.wso2.carbon.identity.jwt.client.extension.dto; import org.wso2.carbon.core.util.Utils; +import org.wso2.carbon.identity.jwt.client.extension.constant.JWTConstants; import java.util.ArrayList; import java.util.List; @@ -20,6 +21,7 @@ public class JWTConfig { private static final String JKS_PASSWORD ="KeyStorePassword"; private static final String JKA_PRIVATE_KEY_PASSWORD = "PrivateKeyPassword"; private static final String TOKEN_ENDPOINT = "TokenEndpoint"; + private static final String JWT_GRANT_TYPE_NAME = "GrantType"; /** * issuer of the JWT @@ -69,6 +71,11 @@ public class JWTConfig { private String privateKeyAlias; private String privateKeyPassword; + /** + * Jwt Grant Type Name + */ + private String jwtGrantType; + /** * @param properties load the config from the properties file. */ @@ -89,6 +96,8 @@ public class JWTConfig { privateKeyAlias = properties.getProperty(JKS_PRIVATE_KEY_ALIAS); privateKeyPassword = properties.getProperty(JKA_PRIVATE_KEY_PASSWORD); tokenEndpoint = properties.getProperty(TOKEN_ENDPOINT, ""); + jwtGrantType = properties.getProperty(JWT_GRANT_TYPE_NAME, JWTConstants.JWT_GRANT_TYPE); + } private static List getAudience(String audience){ @@ -146,4 +155,8 @@ public class JWTConfig { public String getTokenEndpoint() { return Utils.replaceSystemProperty(tokenEndpoint); } + + public String getJwtGrantType() { + return jwtGrantType; + } } diff --git a/features/oauth-extensions/org.wso2.carbon.device.mgt.oauth.extensions.feature/src/main/resources/build.properties b/features/oauth-extensions/org.wso2.carbon.device.mgt.oauth.extensions.feature/src/main/resources/build.properties new file mode 100644 index 00000000000..33bb0980d3c --- /dev/null +++ b/features/oauth-extensions/org.wso2.carbon.device.mgt.oauth.extensions.feature/src/main/resources/build.properties @@ -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 diff --git a/features/oauth-extensions/org.wso2.carbon.device.mgt.oauth.extensions.feature/src/main/resources/device-mgt-scopes.xml b/features/oauth-extensions/org.wso2.carbon.device.mgt.oauth.extensions.feature/src/main/resources/device-mgt-scopes.xml new file mode 100644 index 00000000000..a76191cce0b --- /dev/null +++ b/features/oauth-extensions/org.wso2.carbon.device.mgt.oauth.extensions.feature/src/main/resources/device-mgt-scopes.xml @@ -0,0 +1,51 @@ + + + + + + + + + /permission/device-mgt/user/groups/device_operation + /permission/device-mgt/admin/groups + /permission/device-mgt/user/groups + + + + + /permission/device-mgt/user/groups/device_monitor + /permission/device-mgt/admin/groups + /permission/device-mgt/user/groups + + + + + /permission/device-mgt/user/groups/device_monitor + /permission/device-mgt/admin/groups + /permission/device-mgt/user/groups + + + + + /permission/device-mgt/user/groups/device_operation + /permission/device-mgt/admin/groups + /permission/device-mgt/user/groups + + + \ No newline at end of file diff --git a/features/oauth-extensions/org.wso2.carbon.device.mgt.oauth.extensions.feature/src/main/resources/p2.inf b/features/oauth-extensions/org.wso2.carbon.device.mgt.oauth.extensions.feature/src/main/resources/p2.inf new file mode 100644 index 00000000000..6f97c8724c6 --- /dev/null +++ b/features/oauth-extensions/org.wso2.carbon.device.mgt.oauth.extensions.feature/src/main/resources/p2.inf @@ -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);\ diff --git a/pom.xml b/pom.xml index 41fb7eab3db..f14a0c3a449 100644 --- a/pom.xml +++ b/pom.xml @@ -780,6 +780,11 @@ org.wso2.carbon.apimgt.keymgt.client ${carbon.api.mgt.version} + + org.wso2.carbon.apimgt + org.wso2.carbon.apimgt.keymgt + ${carbon.api.mgt.version} + org.wso2.carbon.apimgt org.wso2.carbon.apimgt.impl