forked from community/device-mgt-core
parent
ba6e202442
commit
250ce1f77c
@ -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,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>
|
||||||
|
* <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>
|
||||||
|
* </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>
|
||||||
|
* <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>
|
||||||
|
* </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>
|
||||||
|
* <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>
|
||||||
|
* </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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.wso2.carbon.device.mgt.oauth.extensions;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This hold the constants related oauth extensions.
|
||||||
|
*/
|
||||||
|
public class Constants {
|
||||||
|
|
||||||
|
public static final String DEFAULT_DEVICE_ASSERTION = "device";
|
||||||
|
public static final String DEFAULT_USERNAME_IDENTIFIER = "username";
|
||||||
|
public static final String DEFAULT_PASSWORD_IDENTIFIER = "password";
|
||||||
|
|
||||||
|
}
|
4
components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedJWTBearerGrantHandler.java → components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedDeviceMgtJWTBearerGrantHandler.java
4
components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedJWTBearerGrantHandler.java → components/identity-extensions/org.wso2.carbon.device.mgt.oauth.extensions/src/main/java/org/wso2/carbon/device/mgt/oauth/extensions/handlers/grant/ExtendedDeviceMgtJWTBearerGrantHandler.java
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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 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.wso2.carbon.apimgt.keymgt.handlers.ExtendedPasswordGrantHandler;
|
||||||
|
import org.wso2.carbon.device.mgt.oauth.extensions.Constants;
|
||||||
|
import org.wso2.carbon.device.mgt.oauth.extensions.DeviceRequestDTO;
|
||||||
|
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 Constants.DEFAULT_USERNAME_IDENTIFIER:
|
||||||
|
String username = parameter.getValue()[0];
|
||||||
|
tokReqMsgCtx.getOauth2AccessTokenReqDTO().setResourceOwnerUsername(username);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Constants.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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.Constants;
|
||||||
|
|
||||||
|
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);
|
||||||
|
requiredParams.add(Constants.DEFAULT_DEVICE_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.Constants;
|
||||||
|
|
||||||
|
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(Constants.DEFAULT_DEVICE_ASSERTION);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue