diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml
new file mode 100644
index 00000000000..e707cbc5f36
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+ apimgt-extensions
+ org.wso2.carbon.devicemgt
+ 2.0.6-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.apimgt.handlers
+ 2.0.6-SNAPSHOT
+ bundle
+ WSO2 Carbon - API Security Handler Component
+ WSO2 Carbon - API Management Security Handler Module
+ http://wso2.org
+
+
+
+
+ org.wso2.carbon
+ org.wso2.carbon.logging
+
+
+ org.apache.synapse
+ synapse-core
+
+
+ org.apache.ws.security.wso2
+ wss4j
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.certificate.mgt.core
+
+
+ org.json.wso2
+ json
+
+
+
+
+
+
+ org.apache.felix
+ maven-scr-plugin
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ 1.4.0
+ true
+
+
+ ${project.artifactId}
+ ${project.artifactId}
+ ${carbon.device.mgt.version}
+ WSO2 Carbon - API Security Handler Component
+
+ org.apache.axiom.*,
+ javax.xml.parsers;version="${javax.xml.parsers.import.pkg.version}";resolution:=optional,
+ javax.xml.*,
+ org.apache.axis2.*,
+ org.apache.commons.*,
+ org.apache.http.*,
+ org.apache.http.util,
+ org.apache.ws.*;version="${org.apache.ws.security.wso2.version}",
+ org.json,
+ org.wso2.carbon.utils,
+ org.wso2.carbon.context,
+ com.google.gson,
+ org.w3c.dom,
+ org.apache.synapse,
+ org.apache.synapse.core.axis2,
+ org.apache.synapse.rest
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/APIMCertificateMGTExcepton.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/APIMCertificateMGTExcepton.java
new file mode 100644
index 00000000000..9b11ab7faf3
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/APIMCertificateMGTExcepton.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.apimgt.handlers;
+
+public class APIMCertificateMGTExcepton extends Exception{
+
+ private static final long serialVersionUID = -37676242646464497L;
+
+ private String errorMessage;
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ public APIMCertificateMGTExcepton(String msg, Exception nestedEx) {
+ super(msg, nestedEx);
+ setErrorMessage(msg);
+ }
+
+ public APIMCertificateMGTExcepton(String message, Throwable cause) {
+ super(message, cause);
+ setErrorMessage(message);
+ }
+
+ public APIMCertificateMGTExcepton(String msg) {
+ super(msg);
+ setErrorMessage(msg);
+ }
+
+ public APIMCertificateMGTExcepton() {
+ super();
+ }
+
+ public APIMCertificateMGTExcepton(Throwable cause) {
+ super(cause);
+ }
+}
+
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/AuthenticationHandler.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/AuthenticationHandler.java
new file mode 100644
index 00000000000..1d4282f1a52
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/AuthenticationHandler.java
@@ -0,0 +1,192 @@
+/*
+ * 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.apimgt.handlers;
+
+import com.google.gson.Gson;
+import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.description.HandlerDescription;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.synapse.core.axis2.Axis2MessageContext;
+import org.apache.synapse.rest.AbstractHandler;
+import org.wso2.carbon.apimgt.handlers.beans.Certificate;
+import org.wso2.carbon.apimgt.handlers.beans.ValidationResponce;
+import org.wso2.carbon.apimgt.handlers.config.IOTServerConfiguration;
+import org.wso2.carbon.apimgt.handlers.invoker.RESTInvoker;
+import org.wso2.carbon.apimgt.handlers.invoker.RESTResponse;
+import org.wso2.carbon.apimgt.handlers.utils.AuthConstants;
+import org.wso2.carbon.apimgt.handlers.utils.Utils;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class AuthenticationHandler extends AbstractHandler {
+ private static final Log log = LogFactory.getLog(AuthenticationHandler.class);
+ private static HandlerDescription EMPTY_HANDLER_METADATA = new HandlerDescription("API Security Handler");
+ private HandlerDescription handlerDesc;
+ private RESTInvoker restInvoker;
+
+ private IOTServerConfiguration iotServerConfiguration;
+
+ /**
+ * Setting up configurations at the constructor
+ */
+ public AuthenticationHandler() {
+ log.info("Engaging API Security Handler..........");
+ restInvoker = new RESTInvoker();
+ this.handlerDesc = EMPTY_HANDLER_METADATA;
+ this.iotServerConfiguration = Utils.initConfig();
+ }
+
+ @Override
+ public boolean handleRequest(org.apache.synapse.MessageContext messageContext) {
+ org.apache.axis2.context.MessageContext axisMC = ((Axis2MessageContext) messageContext).getAxis2MessageContext();
+
+ String ctxPath = messageContext.getTo().getAddress().trim();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Authentication handler invoked by: " + ctxPath);
+ }
+ Map headers = (Map) axisMC.getProperty(MessageContext.TRANSPORT_HEADERS);
+ try {
+ int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
+ RESTResponse response;
+ if (headers.containsKey(AuthConstants.MDM_SIGNATURE)) {
+
+ String mdmSignature = headers.get(AuthConstants.MDM_SIGNATURE).toString();
+ if (log.isDebugEnabled()) {
+ log.debug("Verify Cert:\n" + mdmSignature);
+ }
+ String accessToken = Utils.getAccessToken(iotServerConfiguration);
+
+ String deviceType = this.getDeviceType(messageContext.getTo().getAddress().trim());
+ URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + deviceType);
+
+ Map certVerifyHeaders = new HashMap<>();
+ certVerifyHeaders.put("Authorization", "Bearer " + accessToken);
+ certVerifyHeaders.put("Content-Type", "application/json");
+
+ Certificate certificate = new Certificate();
+ certificate.setPem(mdmSignature);
+ certificate.setTenantId(tenantId);
+ certificate.setSerial("");
+
+ Gson gson = new Gson();
+ String certVerifyContent = gson.toJson(certificate);
+ response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, null,
+ null, certVerifyContent);
+
+ String str = response.getContent();
+ if (str.contains("JWTToken")) {
+ ValidationResponce validationResponce = gson.fromJson(str, ValidationResponce.class);
+ // TODO: send the JWT token with user details.
+ // headers.put("X-JWT-Assertion", validationResponce.getJWTToken());
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Verify response:" + response.getContent());
+ log.debug("Response String : " + str);
+ }
+
+ } else if (headers.containsKey(AuthConstants.PROXY_MUTUAL_AUTH_HEADER)) {
+ String subjectDN = headers.get(AuthConstants.PROXY_MUTUAL_AUTH_HEADER).toString();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Verify subject DN: " + subjectDN);
+ }
+ String accessToken = Utils.getAccessToken(iotServerConfiguration);
+ String deviceType = this.getDeviceType(messageContext.getTo().getAddress().trim());
+ URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + deviceType);
+ Map certVerifyHeaders = new HashMap<>();
+ certVerifyHeaders.put("Authorization", "Bearer " + accessToken);
+ certVerifyHeaders.put("Content-Type", "application/json");
+ Certificate certificate = new Certificate();
+ certificate.setPem(subjectDN);
+ certificate.setTenantId(tenantId);
+ certificate.setSerial(AuthConstants.PROXY_MUTUAL_AUTH_HEADER);
+
+ Gson gson = new Gson();
+ String certVerifyContent = gson.toJson(certificate);
+ response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, null,
+ null, certVerifyContent);
+ if (log.isDebugEnabled()) {
+ log.debug("Verify response:" + response.getContent());
+ }
+ } else if (headers.containsKey(AuthConstants.ENCODED_PEM)) {
+ String encodedPem = headers.get(AuthConstants.ENCODED_PEM).toString();
+ if (log.isDebugEnabled()) {
+ log.debug("Verify Cert:\n" + encodedPem);
+ }
+ String accessToken = Utils.getAccessToken(iotServerConfiguration);
+ URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + "android");
+ Map certVerifyHeaders = new HashMap<>();
+ certVerifyHeaders.put("Authorization", "Bearer " + accessToken);
+ certVerifyHeaders.put("Content-Type", "application/json");
+
+ Certificate certificate = new Certificate();
+ certificate.setPem(encodedPem);
+ certificate.setTenantId(tenantId);
+ certificate.setSerial("");
+ Gson gson = new Gson();
+ String certVerifyContent = gson.toJson(certificate);
+ response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, null,
+ null, certVerifyContent);
+ if (log.isDebugEnabled()) {
+ log.debug("Verify response:" + response.getContent());
+ }
+ } else {
+ log.warn("Unauthorized request for api: " + ctxPath);
+ return false;
+ }
+ if (response != null && !response.getContent().contains("invalid")) {
+ return true;
+ }
+ log.warn("Unauthorized request for api: " + ctxPath);
+ return false;
+ } catch (IOException e) {
+ log.error("Error while processing certificate.", e);
+ return false;
+ } catch (URISyntaxException e) {
+ log.error("Error while processing certificate.", e);
+ return false;
+ } catch (APIMCertificateMGTExcepton e) {
+ log.error("Error while processing certificate.", e);
+ return false;
+ }
+
+ }
+
+ @Override
+ public boolean handleResponse(org.apache.synapse.MessageContext messageContext) {
+ return true;
+ }
+
+
+ // TODO : take this from the url.
+ private String getDeviceType(String url) {
+ if (url.contains("ios")) {
+ return "ios";
+ } else if (url.contains("android")) {
+ return "android";
+ } else return null;
+
+ }
+}
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/Certificate.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/Certificate.java
new file mode 100644
index 00000000000..3f0b65f0aeb
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/Certificate.java
@@ -0,0 +1,52 @@
+/*
+ * 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.apimgt.handlers.beans;
+
+public class Certificate {
+
+ private String pem;
+ private int tenantId;
+ private String serial;
+
+ public String getPem() {
+ return pem;
+ }
+
+ public void setPem(String pem) {
+ this.pem = pem;
+ }
+
+ public int getTenantId() {
+ return tenantId;
+ }
+
+ public void setTenantId(int tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getSerial() {
+ return serial;
+ }
+
+ public void setSerial(String serial) {
+ this.serial = serial;
+ }
+}
+
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/DCR.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/DCR.java
new file mode 100644
index 00000000000..88ae6de8ce0
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/DCR.java
@@ -0,0 +1,61 @@
+/*
+ * 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.apimgt.handlers.beans;
+
+public class DCR {
+
+ private String owner;
+ private String clientName;
+ private String grantType;
+ private String tokenScope;
+
+ public String getOwner() {
+ return owner;
+ }
+
+ public void setOwner(String owner) {
+ this.owner = owner;
+ }
+
+ public String getClientName() {
+ return clientName;
+ }
+
+ public void setClientName(String clientName) {
+ this.clientName = clientName;
+ }
+
+ public String getGrantType() {
+ return grantType;
+ }
+
+ public void setGrantType(String grantType) {
+ this.grantType = grantType;
+ }
+
+ public String getTokenScope() {
+ return tokenScope;
+ }
+
+ public void setTokenScope(String tokenScope) {
+ this.tokenScope = tokenScope;
+ }
+}
+
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/ValidationResponce.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/ValidationResponce.java
new file mode 100644
index 00000000000..5d698fb5a3c
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/ValidationResponce.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, 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.apimgt.handlers.beans;
+
+public class ValidationResponce {
+
+ private String JWTToken; // X-JWT-Assertion
+ private String deviceId;
+ private String deviceType;
+ private int tenantId;
+
+ public String getJWTToken() {
+ return JWTToken;
+ }
+
+ public void setJWTToken(String JWTToken) {
+ this.JWTToken = JWTToken;
+ }
+
+ public String getDeviceId() {
+ return deviceId;
+ }
+
+ public void setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ public String getDeviceType() {
+ return deviceType;
+ }
+
+ public void setDeviceType(String deviceType) {
+ this.deviceType = deviceType;
+ }
+
+ public int getTenantId() {
+ return tenantId;
+ }
+
+ public void setTenantId(int tenantId) {
+ this.tenantId = tenantId;
+ }
+}
+
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/config/IOTServerConfiguration.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/config/IOTServerConfiguration.java
new file mode 100644
index 00000000000..71b430ff405
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/config/IOTServerConfiguration.java
@@ -0,0 +1,118 @@
+/*
+ * 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.apimgt.handlers.config;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlValue;
+import java.util.List;
+
+@XmlRootElement(name = "ServerConfiguration")
+public class IOTServerConfiguration {
+
+ private String hostname;
+ private String verificationEndpoint;
+ private String username;
+ private String password;
+ private String dynamicClientRegistrationEndpoint;
+ private String oauthTokenEndpoint;
+ private List apis;
+
+ @XmlElement(name = "Hostname", required = true)
+ public String getHostname() {
+ return hostname;
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
+
+ @XmlElement(name = "VerificationEndpoint", required = true)
+ public String getVerificationEndpoint() {
+ return verificationEndpoint;
+ }
+
+ public void setVerificationEndpoint(String verificationEndpoint) {
+ this.verificationEndpoint = verificationEndpoint;
+ }
+
+ @XmlElement(name = "Username", required = true)
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ @XmlElement(name = "Password", required = true)
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ @XmlElement(name = "DynamicClientRegistrationEndpoint", required = true)
+ public String getDynamicClientRegistrationEndpoint() {
+ return dynamicClientRegistrationEndpoint;
+ }
+
+ public void setDynamicClientRegistrationEndpoint(String dynamicClientRegistrationEndpoint) {
+ this.dynamicClientRegistrationEndpoint = dynamicClientRegistrationEndpoint;
+ }
+
+ @XmlElement(name = "OauthTokenEndpoint", required = true)
+ public String getOauthTokenEndpoint() {
+ return oauthTokenEndpoint;
+ }
+
+ public void setOauthTokenEndpoint(String oauthTokenEndpoint) {
+ this.oauthTokenEndpoint = oauthTokenEndpoint;
+ }
+
+ @XmlElementWrapper(name="APIS")
+ @XmlElement(name = "ContextPath", required = true)
+ public List getApis() {
+ return apis;
+ }
+
+ public void setApis(List apis) {
+ this.apis = apis;
+ }
+
+ @XmlRootElement(name = "ContextPath")
+ public static class ContextPath {
+
+ private String contextPath;
+
+ @XmlValue()
+ public String getContextPath() {
+ return contextPath;
+ }
+
+ public void setContextPath(String contextPath) {
+ this.contextPath = contextPath;
+ }
+ }
+}
+
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTConstants.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTConstants.java
new file mode 100644
index 00000000000..c1d0413a700
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTConstants.java
@@ -0,0 +1,26 @@
+/*
+ * 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.apimgt.handlers.invoker;
+
+public class RESTConstants {
+ static String REST_CLIENT_CONFIG_ELEMENT = "restClientConfiguration";
+ static String REST_CLIENT_MAX_TOTAL_CONNECTIONS = "maxTotalConnections";
+ static String REST_CLIENT_MAX_CONNECTIONS_PER_ROUTE = "maxConnectionsPerRoute";
+ static String REST_CLEINT_CONNECTION_TIMEOUT = "connectionTimeout";
+ static String REST_CLEINT_SOCKET_TIMEOUT = "socketTimeout";
+}
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTInvoker.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTInvoker.java
new file mode 100644
index 00000000000..95b4fdecca3
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTInvoker.java
@@ -0,0 +1,350 @@
+/*
+ * 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.apimgt.handlers.invoker;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.util.AXIOMUtil;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.Header;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.*;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.util.EntityUtils;
+import org.wso2.carbon.apimgt.handlers.utils.AuthConstants;
+import org.wso2.carbon.apimgt.handlers.utils.CoreUtils;
+import org.wso2.carbon.utils.CarbonUtils;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.Iterator;
+import java.util.Map;
+
+public class RESTInvoker {
+
+ private static final Log log = LogFactory.getLog(RESTInvoker.class);
+
+ private int maxTotalConnections = 100;
+ private int maxTotalConnectionsPerRoute = 100;
+ private int connectionTimeout = 120000;
+ private int socketTimeout = 120000;
+
+ private CloseableHttpClient client = null;
+ private PoolingHttpClientConnectionManager connectionManager = null;
+
+ public RESTInvoker() {
+ configureHttpClient();
+ }
+
+// private void parseConfiguration() {
+// String carbonConfigDirPath = CarbonUtils.getCarbonConfigDirPath();
+// String apiFilterConfigPath = carbonConfigDirPath + File.separator +
+// AuthConstants.AUTH_CONFIGURATION_FILE_NAME;
+// File configFile = new File(apiFilterConfigPath);
+//
+// try {
+// String configContent = FileUtils.readFileToString(configFile);
+// OMElement configElement = AXIOMUtil.stringToOM(configContent);
+// Iterator beans = configElement.getChildrenWithName(
+// new QName("http://www.springframework.org/schema/beans", "bean"));
+//
+// while (beans.hasNext()) {
+// OMElement bean = (OMElement) beans.next();
+// String beanId = bean.getAttributeValue(new QName(null, "id"));
+// if (beanId.equals(RESTConstants.REST_CLIENT_CONFIG_ELEMENT)) {
+// Iterator beanProps = bean.getChildrenWithName(
+// new QName("http://www.springframework.org/schema/beans", "property"));
+//
+// while (beanProps.hasNext()) {
+// OMElement beanProp = (OMElement) beanProps.next();
+// String beanName = beanProp.getAttributeValue(new QName(null, "name"));
+// if (RESTConstants.REST_CLIENT_MAX_TOTAL_CONNECTIONS.equals(beanName)) {
+// String value = beanProp.getAttributeValue(new QName(null, "value"));
+// if (value != null && !value.trim().equals("")) {
+// maxTotalConnections = Integer.parseInt(value);
+// }
+// CoreUtils.debugLog(log, "Max total http connections ", maxTotalConnections);
+// } else if (RESTConstants.REST_CLIENT_MAX_CONNECTIONS_PER_ROUTE.equals(beanName)) {
+// String value = beanProp.getAttributeValue(new QName(null, "value"));
+// if (value != null && !value.trim().equals("")) {
+// maxTotalConnectionsPerRoute = Integer.parseInt(value);
+// }
+// CoreUtils.debugLog(log, "Max total client connections per route ", maxTotalConnectionsPerRoute);
+// } else if (RESTConstants.REST_CLEINT_CONNECTION_TIMEOUT.equals(beanName)) {
+// String value = beanProp.getAttributeValue(new QName(null, "value"));
+// if (value != null && !value.trim().equals("")) {
+// connectionTimeout = Integer.parseInt(value);
+// }
+// } else if (RESTConstants.REST_CLEINT_SOCKET_TIMEOUT.equals(beanName)) {
+// String value = beanProp.getAttributeValue(new QName(null, "value"));
+// if (value != null && !value.trim().equals("")) {
+// socketTimeout = Integer.parseInt(value);
+// }
+// }
+// }
+// }
+// }
+// } catch (XMLStreamException e) {
+// log.error("Error in processing http connection settings, using default settings", e);
+// } catch (IOException e) {
+// log.error("Error in processing http connection settings, using default settings", e);
+// }
+// }
+
+ private void configureHttpClient() {
+
+// parseConfiguration();
+
+ RequestConfig defaultRequestConfig = RequestConfig.custom()
+ .setExpectContinueEnabled(true)
+ .setConnectTimeout(connectionTimeout)
+ .setSocketTimeout(socketTimeout)
+ .build();
+
+ connectionManager = new PoolingHttpClientConnectionManager();
+ connectionManager.setDefaultMaxPerRoute(maxTotalConnectionsPerRoute);
+ connectionManager.setMaxTotal(maxTotalConnections);
+ client = HttpClients.custom()
+ .setConnectionManager(connectionManager)
+ .setDefaultRequestConfig(defaultRequestConfig)
+ .build();
+
+ if(log.isDebugEnabled()){
+ log.debug("REST client initialized with " +
+ "maxTotalConnection = " + maxTotalConnections +
+ "maxConnectionsPerRoute = " + maxTotalConnectionsPerRoute +
+ "connectionTimeout = " + connectionTimeout);
+ }
+//
+// CoreUtils.debugLog(log, "REST client initialized with ",
+// "maxTotalConnection = ", maxTotalConnections,
+// "maxConnectionsPerRoute = ", maxTotalConnectionsPerRoute,
+// "connectionTimeout = ", connectionTimeout);
+ }
+
+ public void closeHttpClient() {
+ IOUtils.closeQuietly(client);
+ IOUtils.closeQuietly(connectionManager);
+ }
+
+ /**
+ * Invokes the http GET method
+ *
+ * @param uri endpoint/service url
+ * @param requestHeaders header list
+ * @param username username for authentication
+ * @param password password for authentication
+ * @return RESTResponse of the GET request (can be the response body or the response status code)
+ * @throws Exception
+ */
+ public RESTResponse invokeGET(URI uri, Map requestHeaders, String username, String password) throws IOException {
+
+ HttpGet httpGet = null;
+ CloseableHttpResponse response = null;
+ Header[] headers;
+ int httpStatus;
+ String contentType;
+ String output;
+ try {
+ httpGet = new HttpGet(uri);
+ if (requestHeaders != null && !requestHeaders.isEmpty()) {
+ Object keys[] = requestHeaders.keySet().toArray();
+ for (Object header : keys) {
+ httpGet.setHeader(header.toString(), requestHeaders.get(header).toString());
+ }
+ }
+ response = sendReceiveRequest(httpGet, username, password);
+ output = IOUtils.toString(response.getEntity().getContent());
+ headers = response.getAllHeaders();
+ httpStatus = response.getStatusLine().getStatusCode();
+ contentType = response.getEntity().getContentType().getValue();
+ if (log.isDebugEnabled()) {
+ log.debug("Invoked GET " + uri.toString() + " - Response message: " + output);
+ }
+ EntityUtils.consume(response.getEntity());
+ } finally {
+ if (response != null) {
+ IOUtils.closeQuietly(response);
+ }
+ if (httpGet != null) {
+ httpGet.releaseConnection();
+ }
+ }
+ return new RESTResponse(contentType, output, headers, httpStatus);
+ }
+
+
+ public RESTResponse invokePOST(URI uri, Map requestHeaders, String username,
+ String password, String payload) throws IOException {
+
+ HttpPost httpPost = null;
+ CloseableHttpResponse response = null;
+ Header[] headers;
+ int httpStatus;
+ String contentType;
+ String output;
+ try {
+ httpPost = new HttpPost(uri);
+ httpPost.setEntity(new StringEntity(payload));
+ if (requestHeaders != null && !requestHeaders.isEmpty()) {
+ Object keys[] = requestHeaders.keySet().toArray();
+ for (Object header : keys) {
+ httpPost.setHeader(header.toString(), requestHeaders.get(header).toString());
+ }
+ }
+ response = sendReceiveRequest(httpPost, username, password);
+ output = IOUtils.toString(response.getEntity().getContent());
+ headers = response.getAllHeaders();
+ httpStatus = response.getStatusLine().getStatusCode();
+ contentType = response.getEntity().getContentType().getValue();
+ if (log.isDebugEnabled()) {
+ log.debug("Invoked POST " + uri.toString() +
+ " - Input payload: " + payload + " - Response message: " + output);
+ }
+ EntityUtils.consume(response.getEntity());
+ } finally {
+ if (response != null) {
+ IOUtils.closeQuietly(response);
+ }
+ if (httpPost != null) {
+ httpPost.releaseConnection();
+ }
+ }
+ return new RESTResponse(contentType, output, headers, httpStatus);
+ }
+
+ /**
+ * Invokes the http PUT method
+ *
+ * @param uri endpoint/service url
+ * @param requestHeaders header list
+ * @param username username for authentication
+ * @param password password for authentication
+ * @param payload payload body passed
+ * @return RESTResponse of the PUT request (can be the response body or the response status code)
+ * @throws Exception
+ */
+ public RESTResponse invokePUT(URI uri, Map requestHeaders, String username, String password,
+ String payload) throws IOException {
+
+ HttpPut httpPut = null;
+ CloseableHttpResponse response = null;
+ Header[] headers;
+ int httpStatus;
+ String contentType;
+ String output;
+ try {
+ httpPut = new HttpPut(uri);
+ httpPut.setEntity(new StringEntity(payload));
+ if (requestHeaders != null && !requestHeaders.isEmpty()) {
+ Object keys[] = requestHeaders.keySet().toArray();
+ for (Object header : keys) {
+ httpPut.setHeader(header.toString(), requestHeaders.get(header).toString());
+ }
+ }
+ response = sendReceiveRequest(httpPut, username, password);
+ output = IOUtils.toString(response.getEntity().getContent());
+ headers = response.getAllHeaders();
+ httpStatus = response.getStatusLine().getStatusCode();
+ contentType = response.getEntity().getContentType().getValue();
+ if (log.isDebugEnabled()) {
+ log.debug("Invoked PUT " + uri.toString() + " - Response message: " + output);
+ }
+ EntityUtils.consume(response.getEntity());
+ } finally {
+ if (response != null) {
+ IOUtils.closeQuietly(response);
+ }
+ if (httpPut != null) {
+ httpPut.releaseConnection();
+ }
+ }
+ return new RESTResponse(contentType, output, headers, httpStatus);
+ }
+
+ /**
+ * Invokes the http DELETE method
+ *
+ * @param uri endpoint/service url
+ * @param requestHeaders header list
+ * @param username username for authentication
+ * @param password password for authentication
+ * @return RESTResponse of the DELETE (can be the response status code or the response body)
+ * @throws Exception
+ */
+ public RESTResponse invokeDELETE(URI uri, Map requestHeaders, String username, String password) throws IOException {
+
+ HttpDelete httpDelete = null;
+ CloseableHttpResponse response = null;
+ Header[] headers;
+ int httpStatus;
+ String contentType;
+ String output;
+ try {
+ httpDelete = new HttpDelete(uri);
+ if (requestHeaders != null && !requestHeaders.isEmpty()) {
+ Object keys[] = requestHeaders.keySet().toArray();
+ for (Object header : keys) {
+ httpDelete.setHeader(header.toString(), requestHeaders.get(header).toString());
+ }
+ }
+ response = sendReceiveRequest(httpDelete, username, password);
+ output = IOUtils.toString(response.getEntity().getContent());
+ headers = response.getAllHeaders();
+ httpStatus = response.getStatusLine().getStatusCode();
+ contentType = response.getEntity().getContentType().getValue();
+ if (log.isDebugEnabled()) {
+ log.debug("Invoked DELETE " + uri.toString() + " - Response message: " + output);
+ }
+ EntityUtils.consume(response.getEntity());
+ } finally {
+ if (response != null) {
+ IOUtils.closeQuietly(response);
+ }
+ if (httpDelete != null) {
+ httpDelete.releaseConnection();
+ }
+ }
+ return new RESTResponse(contentType, output, headers, httpStatus);
+ }
+
+ private CloseableHttpResponse sendReceiveRequest(HttpRequestBase requestBase, String username, String password)
+ throws IOException {
+ CloseableHttpResponse response;
+ if (username != null && !username.equals("") && password != null) {
+ String combinedCredentials = username + ":" + password;
+ byte[] encodedCredentials = Base64.encodeBase64(combinedCredentials.getBytes(StandardCharsets.UTF_8));
+ requestBase.addHeader("Authorization", "Basic " + new String(encodedCredentials));
+
+ response = client.execute(requestBase);
+ } else {
+ response = client.execute(requestBase);
+ }
+ return response;
+ }
+}
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTResponse.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTResponse.java
new file mode 100644
index 00000000000..7ce0389baac
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTResponse.java
@@ -0,0 +1,81 @@
+/*
+ * 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.apimgt.handlers.invoker;
+
+import org.apache.http.Header;
+
+/**
+ * RESTResponse class holds the data retrieved from the HTTP invoke response.
+ */
+public class RESTResponse {
+ private String contentType;
+ private String content;
+ private Header[] headers;
+ private int httpStatus;
+
+ /**
+ * Constructor
+ *
+ * @param contentType from the REST invoke response
+ * @param content from the REST invoke response
+ * @param headers from the REST invoke response
+ * @param httpStatus from the REST invoke response
+ */
+ public RESTResponse(String contentType, String content, Header[] headers, int httpStatus) {
+ this.contentType = contentType;
+ this.content = content;
+ this.headers = headers;
+ this.httpStatus = httpStatus;
+ }
+
+ /**
+ * Get the content type of the EST invoke response
+ *
+ * @return String content type of the response
+ */
+ public String getContentType() {
+ return contentType;
+ }
+
+ /**
+ * Get contents of the REST invoke response
+ *
+ * @return contents of the REST invoke response
+ */
+ public String getContent() {
+ return content;
+ }
+
+ /**
+ * Get headers of the REST invoke response
+ *
+ * @return headers of the REST invoke response
+ */
+ public Header[] getHeaders() {
+ return headers;
+ }
+
+ /**
+ * Get the HTTP Status code from REST invoke response
+ *
+ * @return int HTTP status code
+ */
+ public int getHttpStatus() {
+ return httpStatus;
+ }
+}
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/AuthConstants.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/AuthConstants.java
new file mode 100644
index 00000000000..03a8780efc9
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/AuthConstants.java
@@ -0,0 +1,36 @@
+/*
+ * 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.apimgt.handlers.utils;
+
+public class AuthConstants {
+ public static final String SEC_FAULT = "SECURITY_VALIDATION_FAILURE";
+ public static final String HTTPS = "https";
+ public static final String WSSE = "wsse";
+ public static final String AUTH_CONFIGURATION_FILE_NAME = "api-filter-config.xml";
+ public static final String API_FILTER_CONFIG_ELEMENT = "apiFilterConfig";
+ public static final String API_LIST_PROPERTY = "apiList";
+ public static final String HOST = "host";
+ public static final String HTTPS_PORT = "httpsPort";
+ public static final String USERNAME = "username";
+ public static final String PASSWORD = "password";
+ public static final String IOS_VERIFY_ENDPOINT = "ios-verify-endpoint";
+ public static final String ANDROID_VERIFY_ENDPOINT = "android-verify-endpoint";
+ public static final String MDM_SIGNATURE = "mdm-signature";
+ public static final String PROXY_MUTUAL_AUTH_HEADER = "proxy-mutual-auth-header";
+ public static final String ENCODED_PEM = "encoded-pem";
+}
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/CoreUtils.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/CoreUtils.java
new file mode 100644
index 00000000000..605ad801e6d
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/CoreUtils.java
@@ -0,0 +1,156 @@
+/*
+ * 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.apimgt.handlers.utils;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.util.AXIOMUtil;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.utils.CarbonUtils;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+public class CoreUtils {
+ private static final Log log = LogFactory.getLog(CoreUtils.class);
+ private static String host = "localhost";
+ private static int httpsPort = 9443;
+ private static String username = "admin";
+ private static String password = "admin";
+ private static String iosVerifyEndpoint = "/api/certificate-mgt/v1.0/admin/certificates/verify/ios";
+ private static String androidVerifyEndpoint = "/api/certificate-mgt/v1.0/admin/certificates/verify/android";
+
+// /**
+// * Reading configurations from api-filter-config.xml file
+// *
+// * @return ArrayList of api contexts
+// */
+// public static ArrayList readApiFilterList() {
+// ArrayList apiList = new ArrayList();
+// String carbonConfigDirPath = CarbonUtils.getCarbonConfigDirPath();
+// String apiFilterConfigPath = carbonConfigDirPath + File.separator +
+// AuthConstants.AUTH_CONFIGURATION_FILE_NAME;
+// File configFile = new File(apiFilterConfigPath);
+//
+// try {
+// String configContent = FileUtils.readFileToString(configFile);
+// OMElement configElement = AXIOMUtil.stringToOM(configContent);
+// Iterator beans = configElement.getChildrenWithName(
+// new QName("http://www.springframework.org/schema/beans", "bean"));
+//
+// while (beans.hasNext()) {
+// OMElement bean = (OMElement) beans.next();
+// String beanId = bean.getAttributeValue(new QName(null, "id"));
+// if (beanId.equals(AuthConstants.API_FILTER_CONFIG_ELEMENT)) {
+// Iterator beanProps = bean.getChildrenWithName(
+// new QName("http://www.springframework.org/schema/beans", "property"));
+//
+// while (beanProps.hasNext()) {
+// OMElement beanProp = (OMElement) beanProps.next();
+// String beanName = beanProp.getAttributeValue(new QName(null, "name"));
+// if (AuthConstants.API_LIST_PROPERTY.equals(beanName)) {
+// Iterator apiListSet = ((OMElement) beanProp.getChildrenWithLocalName("set").next())
+// .getChildrenWithLocalName("value");
+// while (apiListSet.hasNext()) {
+// String apiContext = ((OMElement) apiListSet.next()).getText();
+// apiList.add(apiContext);
+// CoreUtils.debugLog(log, "Adding security to api: ", apiContext);
+// }
+// } else if (AuthConstants.HOST.equals(beanName)) {
+// String value = beanProp.getAttributeValue(new QName(null, "value"));
+// host = value;
+// } else if (AuthConstants.HTTPS_PORT.equals(beanName)) {
+// String value = beanProp.getAttributeValue(new QName(null, "value"));
+// if (value != null && !value.trim().equals("")) {
+// httpsPort = Integer.parseInt(value);
+// }
+// } else if (AuthConstants.USERNAME.equals(beanName)) {
+// String value = beanProp.getAttributeValue(new QName(null, "value"));
+// username = value;
+// } else if (AuthConstants.PASSWORD.equals(beanName)) {
+// String value = beanProp.getAttributeValue(new QName(null, "value"));
+// password = value;
+// } else if (AuthConstants.IOS_VERIFY_ENDPOINT.equals(beanName)) {
+// String value = beanProp.getAttributeValue(new QName(null, "value"));
+// iosVerifyEndpoint = value;
+// } else if (AuthConstants.ANDROID_VERIFY_ENDPOINT.equals(beanName)) {
+// String value = beanProp.getAttributeValue(new QName(null, "value"));
+// androidVerifyEndpoint = value;
+// }
+// }
+// }
+// }
+// } catch (IOException e) {
+// log.error("Error in reading api filter settings", e);
+// } catch (XMLStreamException e) {
+// log.error("Error in reading api filter settings", e);
+// }
+// return apiList;
+// }
+//
+// /**
+// * Universal debug log function
+// *
+// * @param logger Log object specific to the class
+// * @param message initial debug log message
+// * @param vars optional strings to be appended for the log
+// */
+// public static void debugLog(Log logger, String message, Object ... vars) {
+// if(logger.isDebugEnabled()) {
+// if (vars.length < 1) {
+// logger.debug(message);
+// return;
+// }
+// StringBuilder stringBuilder = new StringBuilder();
+// stringBuilder.append(message);
+// for (Object var : vars) {
+// stringBuilder.append(var.toString());
+// }
+// logger.debug(stringBuilder.toString());
+// }
+// }
+
+ public static String getHost() {
+ return host;
+ }
+
+ public static int getHttpsPort() {
+ return httpsPort;
+ }
+
+ public static String getUsername() {
+ return username;
+ }
+
+ public static String getPassword() {
+ return password;
+ }
+
+ public static String getIosVerifyEndpoint() {
+ return iosVerifyEndpoint;
+ }
+
+ public static String getAndroidVerifyEndpoint() {
+ return androidVerifyEndpoint;
+ }
+}
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/Utils.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/Utils.java
new file mode 100644
index 00000000000..416ae306ae9
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/Utils.java
@@ -0,0 +1,154 @@
+/*
+ * 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.apimgt.handlers.utils;
+
+import com.google.gson.Gson;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.util.Base64;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.w3c.dom.Document;
+import org.wso2.carbon.apimgt.handlers.APIMCertificateMGTExcepton;
+import org.wso2.carbon.apimgt.handlers.beans.DCR;
+import org.wso2.carbon.apimgt.handlers.config.IOTServerConfiguration;
+import org.wso2.carbon.apimgt.handlers.invoker.RESTInvoker;
+import org.wso2.carbon.apimgt.handlers.invoker.RESTResponse;
+import org.wso2.carbon.utils.CarbonUtils;
+
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Utils {
+
+ private static final Log log = LogFactory.getLog(Utils.class);
+ private static final String IOT_APIS_CONFIG_FILE = "iot-api-config.xml";
+ private static String clientId;
+ private static String clientSecret;
+
+ public static IOTServerConfiguration initConfig() {
+ try {
+
+ String IOTServerAPIConfigurationPath =
+ CarbonUtils.getCarbonConfigDirPath() + File.separator + IOT_APIS_CONFIG_FILE;
+ File file = new File(IOTServerAPIConfigurationPath);
+ Document doc = Utils.convertToDocument(file);
+
+ JAXBContext fileContext = JAXBContext.newInstance(IOTServerConfiguration.class);
+ Unmarshaller unmarshaller = fileContext.createUnmarshaller();
+ return (IOTServerConfiguration) unmarshaller.unmarshal(doc);
+
+ } catch (JAXBException | APIMCertificateMGTExcepton e) {
+ log.error("Error occurred while initializing Data Source config", e);
+ return null;
+ }
+ }
+
+ public static Document convertToDocument(File file) throws APIMCertificateMGTExcepton {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ try {
+ DocumentBuilder docBuilder = factory.newDocumentBuilder();
+ factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ return docBuilder.parse(file);
+ } catch (Exception e) {
+ throw new APIMCertificateMGTExcepton("Error occurred while parsing file, while converting " +
+ "to a org.w3c.dom.Document", e);
+ }
+ }
+
+ public static String getAccessToken(IOTServerConfiguration iotServerConfiguration)
+ throws APIMCertificateMGTExcepton {
+ try {
+ if (clientId == null || clientSecret == null) {
+ getClientSecretes(iotServerConfiguration);
+ }
+ URI tokenUrl = new URI(iotServerConfiguration.getOauthTokenEndpoint());
+ String tokenContent = "grant_type=password&username=" + iotServerConfiguration.getUsername()+ "&password=" +
+ iotServerConfiguration.getPassword() + "&scope=activity-view";
+ String tokenBasicAuth = "Basic " + Base64.encode((clientId + ":" + clientSecret).getBytes());
+ Map tokenHeaders = new HashMap();
+ tokenHeaders.put("Authorization", tokenBasicAuth);
+ tokenHeaders.put("Content-Type", "application/x-www-form-urlencoded");
+
+ RESTInvoker restInvoker = new RESTInvoker();
+ RESTResponse response = restInvoker.invokePOST(tokenUrl, tokenHeaders, null,
+ null, tokenContent);
+ if(log.isDebugEnabled()) {
+ log.debug("Token response:" + response.getContent());
+ }
+ JSONObject jsonResponse = new JSONObject(response.getContent());
+ String accessToken = jsonResponse.getString("access_token");
+ return accessToken;
+
+ } catch (URISyntaxException e) {
+ throw new APIMCertificateMGTExcepton("Error occurred while trying to call oauth token endpoint", e);
+ } catch (JSONException e) {
+ throw new APIMCertificateMGTExcepton("Error occurred while converting the json to object", e);
+ } catch (IOException e) {
+ throw new APIMCertificateMGTExcepton("Error occurred while trying to call oauth token endpoint", e);
+ }
+ }
+
+ private static void getClientSecretes(IOTServerConfiguration iotServerConfiguration)
+ throws APIMCertificateMGTExcepton {
+ try {
+ DCR dcr = new DCR();
+ dcr.setOwner(iotServerConfiguration.getUsername());
+ dcr.setClientName("IOT-API-MANAGER");
+ dcr.setGrantType("refresh_token password client_credentials");
+ dcr.setTokenScope("default");
+ Gson gson = new Gson();
+ String dcrContent = gson.toJson(dcr);
+ Map drcHeaders = new HashMap();
+ drcHeaders.put("Content-Type", "application/json");
+ URI dcrUrl = new URI(iotServerConfiguration.getDynamicClientRegistrationEndpoint());
+ RESTInvoker restInvoker = new RESTInvoker();
+ RESTResponse response = restInvoker.invokePOST(dcrUrl, drcHeaders, null,
+ null, dcrContent);
+
+ if (log.isDebugEnabled()) {
+ log.debug("DCR response :" + response.getContent());
+ }
+ JSONObject jsonResponse = new JSONObject(response.getContent());
+ clientId = jsonResponse.getString("client_id");
+ clientSecret = jsonResponse.getString("client_secret");
+ } catch (JSONException e) {
+ throw new APIMCertificateMGTExcepton("Error occurred while converting the json to object", e);
+ } catch (IOException e) {
+ throw new APIMCertificateMGTExcepton("Error occurred while trying to call DCR endpoint", e);
+ } catch (URISyntaxException e) {
+ throw new APIMCertificateMGTExcepton("Error occurred while trying to call DCR endpoint", e);
+ }
+
+ }
+
+}
+
diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/resources/iot-api-config.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/resources/iot-api-config.xml
new file mode 100644
index 00000000000..fc65693d281
--- /dev/null
+++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/resources/iot-api-config.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+ https://localhost:9443/
+
+
+ https://localhost:9443/api/certificate-mgt/v1.0/admin/certificates/verify/
+
+
+ admin
+ admin
+
+
+ https://localhost:9443/dynamic-client-web/register
+
+
+ https://localhost:9443/oauth2/token
+
+
+ /services/echo
+
+
\ No newline at end of file
diff --git a/components/apimgt-extensions/pom.xml b/components/apimgt-extensions/pom.xml
index 850097bc1b2..b0ef6f0a7b2 100644
--- a/components/apimgt-extensions/pom.xml
+++ b/components/apimgt-extensions/pom.xml
@@ -38,6 +38,7 @@
org.wso2.carbon.apimgt.application.extension
org.wso2.carbon.apimgt.application.extension.api
org.wso2.carbon.apimgt.annotations
+ org.wso2.carbon.apimgt.handlers
diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml
index 377b33ea3e0..4c572152a9b 100644
--- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml
+++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml
@@ -149,6 +149,11 @@
org.wso2.carbon.certificate.mgt.core
provided
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.identity.jwt.client.extension
+ provided
+
io.swagger
swagger-annotations
diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java
index 69a10a16d8a..14d06f00f04 100644
--- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java
+++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java
@@ -18,6 +18,7 @@ import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.EnrollmentCertificat
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ErrorResponse;
import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse;
+import javax.validation.constraints.Size;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -337,4 +338,125 @@ public interface CertificateManagementAdminService {
defaultValue = "12438035315552875930")
@PathParam("serialNumber") String serialNumber);
+// /**
+// * Verify IOS Certificate for the API security filter
+// *
+// * @param certificate to be verified as a String
+// * @return Status of the certificate verification.
+// */
+// @POST
+// @Path("/verify/ios")
+// @ApiOperation(
+// consumes = MediaType.APPLICATION_JSON,
+// produces = MediaType.APPLICATION_JSON,
+// httpMethod = "POST",
+// value = "Verify IOS SSL certificate",
+// notes = "Verify IOS Certificate for the API security filter.\n",
+// tags = "Certificate Management")
+// @ApiResponses(
+// value = {
+// @ApiResponse(
+// code = 200,
+// message = "Return the status of the IOS certificate verification.",
+// responseHeaders = {
+// @ResponseHeader(
+// name = "Content-Type",
+// description = "The content type of the body")}),
+// @ApiResponse(
+// code = 400,
+// message = "Bad Request. \n Invalid request or validation error.",
+// response = ErrorResponse.class)
+// })
+// Response verifyIOSCertificate(
+// @ApiParam(
+// name = "certificate",
+// value = "The properties to verify certificate. It includes the following: \n" +
+// "serial: The unique ID of the certificate. (optional) \n" +
+// "pem: mdm-signature of the certificate",
+// required = true) EnrollmentCertificate certificate);
+//
+// /**
+// * Verify Android Certificate for the API security filter
+// *
+// * @param certificate to be verified as a String
+// * @return Status of the certificate verification.
+// */
+// @POST
+// @Path("/verify/android")
+// @ApiOperation(
+// consumes = MediaType.APPLICATION_JSON,
+// produces = MediaType.APPLICATION_JSON,
+// httpMethod = "POST",
+// value = "Verify Android SSL certificate",
+// notes = "Verify Android Certificate for the API security filter.\n",
+// tags = "Certificate Management")
+// @ApiResponses(
+// value = {
+// @ApiResponse(
+// code = 200,
+// message = "Return the status of the Android certificate verification.",
+// responseHeaders = {
+// @ResponseHeader(
+// name = "Content-Type",
+// description = "The content type of the body")}),
+// @ApiResponse(
+// code = 400,
+// message = "Bad Request. \n Invalid request or validation error.",
+// response = ErrorResponse.class)
+// })
+// Response verifyAndroidCertificate(
+// @ApiParam(
+// name = "certificate",
+// value = "The properties to verify certificate. It includes the following: \n" +
+// "serial: The unique ID of the certificate. (optional) \n" +
+// "pem: pem String of the certificate",
+// required = true) EnrollmentCertificate certificate);
+//
+
+
+ /**
+ * Verify Android Certificate for the API security filter
+ *
+ * @param certificate to be verified as a String
+ * @return Status of the certificate verification.
+ */
+ @POST
+ @Path("/verify/{type}")
+ @ApiOperation(
+ consumes = MediaType.APPLICATION_JSON,
+ produces = MediaType.APPLICATION_JSON,
+ httpMethod = "POST",
+ value = "Verify Android SSL certificate",
+ notes = "Verify Android Certificate for the API security filter.\n",
+ tags = "Certificate Management")
+ @ApiResponses(
+ value = {
+ @ApiResponse(
+ code = 200,
+ message = "Return the status of the Android certificate verification.",
+ responseHeaders = {
+ @ResponseHeader(
+ name = "Content-Type",
+ description = "The content type of the body")}),
+ @ApiResponse(
+ code = 400,
+ message = "Bad Request. \n Invalid request or validation error.",
+ response = ErrorResponse.class)
+ })
+ Response verifyCertificate(
+ @ApiParam(
+ name = "type",
+ value = "The device type, such as ios, android or windows.",
+ required = true,
+ allowableValues = "android, ios, windows")
+ @PathParam("type")
+ @Size(max = 45)
+ String type,
+ @ApiParam(
+ name = "certificate",
+ value = "The properties to verify certificate. It includes the following: \n" +
+ "serial: The unique ID of the certificate. (optional) \n" +
+ "pem: pem String of the certificate",
+ required = true) EnrollmentCertificate certificate);
}
+
diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponce.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponce.java
new file mode 100644
index 00000000000..5a72112e4d6
--- /dev/null
+++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponce.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, 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.certificate.mgt.cert.jaxrs.api.beans;
+
+public class ValidationResponce {
+
+ private String JWTToken; // X-JWT-Assertion
+ private String deviceId;
+ private String deviceType;
+ private int tenantId;
+
+ public String getJWTToken() {
+ return JWTToken;
+ }
+
+ public void setJWTToken(String JWTToken) {
+ this.JWTToken = JWTToken;
+ }
+
+ public String getDeviceId() {
+ return deviceId;
+ }
+
+ public void setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ public String getDeviceType() {
+ return deviceType;
+ }
+
+ public void setDeviceType(String deviceType) {
+ this.deviceType = deviceType;
+ }
+
+ public int getTenantId() {
+ return tenantId;
+ }
+
+ public void setTenantId(int tenantId) {
+ this.tenantId = tenantId;
+ }
+}
+
diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java
index e0f0852787c..0f62d9e72b8 100644
--- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java
+++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java
@@ -6,14 +6,22 @@ import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.CertificateManagementAdmin
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.CertificateList;
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.EnrollmentCertificate;
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ErrorResponse;
+import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ValidationResponce;
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.CertificateMgtAPIUtils;
import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.RequestValidationUtil;
import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse;
import org.wso2.carbon.certificate.mgt.core.exception.CertificateManagementException;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
+import org.wso2.carbon.certificate.mgt.core.scep.SCEPException;
+import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager;
+import org.wso2.carbon.certificate.mgt.core.scep.TenantedDeviceWrapper;
import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService;
import org.wso2.carbon.certificate.mgt.core.service.PaginationResult;
import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
+import org.wso2.carbon.device.mgt.common.DeviceManagementConstants;
+import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
+import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
@@ -25,6 +33,7 @@ import java.util.List;
public class CertificateManagementAdminServiceImpl implements CertificateManagementAdminService {
private static Log log = LogFactory.getLog(CertificateManagementAdminServiceImpl.class);
+ private static final String PROXY_AUTH_MUTUAL_HEADER = "proxy-mutual-auth-header";
/**
* Save a list of certificates and relevant information in the database.
@@ -138,4 +147,138 @@ public class CertificateManagementAdminServiceImpl implements CertificateManagem
}
}
+// @POST
+// @Path("/verify/ios")
+// public Response verifyIOSCertificate(@ApiParam(name = "certificate", value = "Mdm-Signature of the " +
+// "certificate that needs to be verified", required = true) EnrollmentCertificate certificate) {
+// try {
+// CertificateManagementService certMgtService = CertificateMgtAPIUtils.getCertificateManagementService();
+// X509Certificate cert = certMgtService.extractCertificateFromSignature(certificate.getPem());
+// String challengeToken = certMgtService.extractChallengeToken(cert);
+//
+// if (challengeToken != null) {
+// challengeToken = challengeToken.substring(challengeToken.indexOf("(") + 1).trim();
+//
+// SCEPManager scepManager = CertificateMgtAPIUtils.getSCEPManagerService();
+// DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
+// deviceIdentifier.setId(challengeToken);
+// deviceIdentifier.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS);
+// TenantedDeviceWrapper tenantedDeviceWrapper = scepManager.getValidatedDevice(deviceIdentifier);
+//
+// if (tenantedDeviceWrapper != null) {
+// return Response.status(Response.Status.OK).entity("valid").build();
+// }
+// }
+// } catch (SCEPException e) {
+// String msg = "Error occurred while extracting information from certificate.";
+// log.error(msg, e);
+// return Response.serverError().entity(
+// new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build();
+// } catch (KeystoreException e) {
+// String msg = "Error occurred while converting PEM file to X509Certificate.";
+// log.error(msg, e);
+// return Response.serverError().entity(
+// new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build();
+// }
+// return Response.status(Response.Status.OK).entity("invalid").build();
+// }
+//
+// @POST
+// @Path("/verify/android")
+// public Response verifyAndroidCertificate(@ApiParam(name = "certificate", value = "Base64 encoded .pem file of the " +
+// "certificate that needs to be verified", required = true) EnrollmentCertificate certificate) {
+// CertificateResponse certificateResponse = null;
+// try {
+// CertificateManagementService certMgtService = CertificateMgtAPIUtils.getCertificateManagementService();
+// if (certificate.getSerial().toLowerCase().contains(PROXY_AUTH_MUTUAL_HEADER)) {
+// certificateResponse = certMgtService.verifySubjectDN(certificate.getPem());
+// } else {
+// X509Certificate clientCertificate = certMgtService.pemToX509Certificate(certificate.getPem());
+// if (clientCertificate != null) {
+// certificateResponse = certMgtService.verifyPEMSignature(clientCertificate);
+// }
+// }
+//
+// if (certificateResponse != null && certificateResponse.getCommonName() != null && !certificateResponse
+// .getCommonName().isEmpty()) {
+// return Response.status(Response.Status.OK).entity("valid").build();
+// }
+// } catch (KeystoreException e) {
+// String msg = "Error occurred while converting PEM file to X509Certificate.";
+// log.error(msg, e);
+// return Response.serverError().entity(
+// new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build();
+// }
+// return Response.status(Response.Status.OK).entity("invalid").build();
+// }
+
+ @POST
+ @Path("/verify/{type}")
+ public Response verifyCertificate(@PathParam("type") String type, EnrollmentCertificate certificate) {
+ try {
+ CertificateManagementService certMgtService = CertificateMgtAPIUtils.getCertificateManagementService();
+
+ if (DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS.equalsIgnoreCase(type)) {
+ X509Certificate cert = certMgtService.extractCertificateFromSignature(certificate.getPem());
+ String challengeToken = certMgtService.extractChallengeToken(cert);
+
+ if (challengeToken != null) {
+ challengeToken = challengeToken.substring(challengeToken.indexOf("(") + 1).trim();
+
+ SCEPManager scepManager = CertificateMgtAPIUtils.getSCEPManagerService();
+ DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
+ deviceIdentifier.setId(challengeToken);
+ deviceIdentifier.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS);
+ TenantedDeviceWrapper tenantedDeviceWrapper = scepManager.getValidatedDevice(deviceIdentifier);
+
+ JWTClientManagerService jwtClientManagerService = CertificateMgtAPIUtils.getJwtClientManagerService();
+ String jwdToken = jwtClientManagerService.getJWTClient().getJwtToken(
+ tenantedDeviceWrapper.getDevice().getEnrolmentInfo().getOwner());
+
+ ValidationResponce validationResponce = new ValidationResponce();
+ validationResponce.setDeviceId(challengeToken);
+ validationResponce.setDeviceType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS);
+ validationResponce.setJWTToken(jwdToken);
+ validationResponce.setTenantId(tenantedDeviceWrapper.getTenantId());
+
+ if (tenantedDeviceWrapper != null) {
+ return Response.status(Response.Status.OK).entity(validationResponce).build();
+ }
+ }
+ }
+
+ if (DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_ANDROID.equalsIgnoreCase(type)) {
+ CertificateResponse certificateResponse = null;
+ if (certificate.getSerial().toLowerCase().contains(PROXY_AUTH_MUTUAL_HEADER)) {
+ certificateResponse = certMgtService.verifySubjectDN(certificate.getPem());
+ } else {
+ X509Certificate clientCertificate = certMgtService.pemToX509Certificate(certificate.getPem());
+ if (clientCertificate != null) {
+ certificateResponse = certMgtService.verifyPEMSignature(clientCertificate);
+ }
+ }
+
+ if (certificateResponse != null && certificateResponse.getCommonName() != null && !certificateResponse
+ .getCommonName().isEmpty()) {
+ return Response.status(Response.Status.OK).entity("valid").build();
+ }
+ }
+ } catch (SCEPException e) {
+ String msg = "Error occurred while extracting information from certificate.";
+ log.error(msg, e);
+ return Response.serverError().entity(
+ new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build();
+ } catch (KeystoreException e) {
+ String msg = "Error occurred while converting PEM file to X509Certificate.";
+ log.error(msg, e);
+ return Response.serverError().entity(
+ new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build();
+ } catch (JWTClientException e) {
+ String msg = "Error occurred while converting PEM file to X509Certificate.";
+ log.error(msg, e);
+ return Response.serverError().entity(
+ new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build();
+ }
+ return Response.status(Response.Status.OK).entity("invalid").build();
+ }
}
\ No newline at end of file
diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/CertificateMgtAPIUtils.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/CertificateMgtAPIUtils.java
index a96b013b7b5..fc5264c4db4 100644
--- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/CertificateMgtAPIUtils.java
+++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/CertificateMgtAPIUtils.java
@@ -20,9 +20,11 @@ package org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager;
import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.core.search.mgt.SearchManagerService;
+import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import javax.ws.rs.core.MediaType;
@@ -50,6 +52,37 @@ public class CertificateMgtAPIUtils {
}
+ public static JWTClientManagerService getJwtClientManagerService() {
+ PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ JWTClientManagerService jwtClientManagerService = (JWTClientManagerService)
+ ctx.getOSGiService(JWTClientManagerService.class, null);
+
+ if (jwtClientManagerService == null) {
+ String msg = "JWTClientManagerService Management service not initialized.";
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+
+ return jwtClientManagerService;
+ }
+
+
+ public static SCEPManager getSCEPManagerService() {
+
+ PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ SCEPManager scepManagerService = (SCEPManager)
+ ctx.getOSGiService(SCEPManager.class, null);
+
+ if (scepManagerService == null) {
+ String msg = "SCEPManagerImpl Management service not initialized.";
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+
+ return scepManagerService;
+ }
+
+
public static MediaType getResponseMediaType(String acceptHeader) {
MediaType responseMediaType;
if (acceptHeader == null || MediaType.WILDCARD.equals(acceptHeader)) {
diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml
index cbc9281c545..ff4d481e493 100644
--- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml
+++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml
@@ -51,7 +51,8 @@
${carbon.device.mgt.version}
Device Management Core Bundle
- org.wso2.carbon.certificate.mgt.core.internal
+ org.wso2.carbon.certificate.mgt.core.internal,
+ org.wso2.carbon.certificate.mgt.core.util
org.osgi.framework,
@@ -59,7 +60,7 @@
org.apache.commons.logging,
javax.security.auth.x500,
javax.xml.*,
- javax.xml.parsers;version="${javax.xml.parsers.import.pkg.version}";resolution:=optional,
+ javax.xml.parsers;version="${javax.xml.parsers.import.pkg.version}";resolution:=optional,
org.apache.commons.codec.binary,
org.bouncycastle.asn1,
org.bouncycastle.asn1.x500,
@@ -97,6 +98,7 @@
!org.wso2.carbon.certificate.mgt.core.internal.*,
+ !org.wso2.carbon.certificate.mgt.core.util,
org.wso2.carbon.certificate.mgt.core.*
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/jaggery.conf b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/jaggery.conf
index fb71f60e969..832c1ab2528 100644
--- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/jaggery.conf
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/jaggery.conf
@@ -108,7 +108,7 @@
"contextParams" : [
{
"name" : "Owasp.CsrfGuard.Config",
- "value" : "/repository/conf/security/Owasp.CsrfGuard.Carbon.properties"
+ "value" : "/repository/conf/security/Owasp.CsrfGuard.dashboard.properties"
}
]
}
\ No newline at end of file
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/jaggery.conf b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/jaggery.conf
index 7c5a2d41c9d..f97bae72cfc 100644
--- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/jaggery.conf
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/jaggery.conf
@@ -71,7 +71,7 @@
"contextParams" : [
{
"name" : "Owasp.CsrfGuard.Config",
- "value" : "/repository/conf/security/Owasp.CsrfGuard.Carbon.properties"
+ "value" : "/repository/conf/security/Owasp.CsrfGuard.dashboard.properties"
}
]
}
\ No newline at end of file
diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js
index 2cf9771beab..a18d2efc501 100644
--- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js
+++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js
@@ -520,7 +520,7 @@ var module = {};
response.sendError(500, msg);
return;
}
-
+
/**
* @type {{sessionId: string, loggedInUser: string, sessionIndex: string, samlToken:
* string}}
@@ -533,7 +533,7 @@ var module = {};
if (ssoSession.sessionIndex) {
module.loadTenant(ssoSession.loggedInUser);
var carbonUser = (require("carbon")).server.tenantUser(ssoSession.loggedInUser);
- module.loadTenant(ssoSession.loggedInUser);
+ module.loadTenant(ssoSession.loggedInUser);
utils.setCurrentUser(carbonUser.username, carbonUser.domain, carbonUser.tenantId);
var scriptArgument = {input: {samlToken: ssoSession.samlToken}, user: module.getCurrentUser()};
handleEvent(OPERATION_LOGIN, EVENT_SUCCESS, scriptArgument);
diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml
index 84d43cec1f3..4d3056bf11a 100644
--- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml
+++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml
@@ -17,7 +17,8 @@
~ under the License.
-->
-
+
org.wso2.carbon.devicemgt
webapp-authenticator-framework
@@ -81,7 +82,8 @@
org.wso2.carbon.core.util,
org.wso2.carbon.identity.base; version="${carbon.identity.imp.pkg.version}",
org.wso2.carbon.identity.core.util; version="${carbon.identity.imp.pkg.version}",
- org.wso2.carbon.identity.oauth2.*; version="${carbon.identity-inbound-auth-oauth.imp.pkg.version}",
+ org.wso2.carbon.identity.oauth2.*;
+ version="${carbon.identity-inbound-auth-oauth.imp.pkg.version}",
org.wso2.carbon.tomcat.ext.valves,
org.wso2.carbon.user.api,
org.wso2.carbon.user.core.service,
@@ -111,7 +113,7 @@
org.apache.http.impl.conn,
javax.xml.soap; version="${javax.xml.soap.imp.pkg.version}",
javax.xml.stream,
- org.apache.axiom.*; version="${axiom.osgi.version.range}",
+ org.apache.axiom.*; version="${axiom.osgi.version.range}",
org.wso2.carbon.registry.core.*,
org.wso2.carbon.registry.common.*;version="${carbon.registry.imp.pkg.version.range}",
org.wso2.carbon.registry.indexing.*; version="${carbon.registry.imp.pkg.version.range}",
diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/pom.xml b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/pom.xml
new file mode 100644
index 00000000000..fceb11b4e1b
--- /dev/null
+++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/pom.xml
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+ org.wso2.carbon.devicemgt
+ apimgt-extensions-feature
+ 2.0.6-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.apimgt.handler.server.feature
+ pom
+ 2.0.6-SNAPSHOT
+ WSO2 Carbon - Device Management - APIM handler Server Feature
+ http://wso2.org
+ This feature contains the handler for the api authentications
+
+
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.apimgt.handlers
+
+
+
+
+
+
+ maven-resources-plugin
+ 2.6
+
+
+ copy-resources
+ generate-resources
+
+ copy-resources
+
+
+ src/main/resources
+
+
+ resources
+
+ build.properties
+ p2.inf
+
+
+
+
+
+
+
+
+ org.wso2.maven
+ carbon-p2-plugin
+ ${carbon.p2.plugin.version}
+
+
+ p2-feature-generation
+ package
+
+ p2-feature-gen
+
+
+ org.wso2.carbon.apimgt.handler.server
+ ../../../features/etc/feature.properties
+
+
+ org.wso2.carbon.p2.category.type:server
+ org.eclipse.equinox.p2.type.group:false
+
+
+
+
+ org.wso2.carbon.devicemgt:org.wso2.carbon.apimgt.handlers:${carbon.device.mgt.version}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/build.properties b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/build.properties
new file mode 100644
index 00000000000..9c86577d768
--- /dev/null
+++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/build.properties
@@ -0,0 +1 @@
+custom = true
diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/conf/iot-api-config.xml b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/conf/iot-api-config.xml
new file mode 100644
index 00000000000..c9a210d3bf2
--- /dev/null
+++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/conf/iot-api-config.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+ https://localhost:9443/
+
+
+ https://localhost:9443/api/certificate-mgt/v1.0/admin/certificates/verify/
+
+
+ admin
+ admin
+
+
+ https://localhost:9443/dynamic-client-web/register
+
+
+ https://localhost:9443/oauth2/token
+
+
+ /services
+
+
\ No newline at end of file
diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/p2.inf b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/p2.inf
new file mode 100644
index 00000000000..e7c6acf89f2
--- /dev/null
+++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.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.apimgt.handler.server_${feature.version}/conf/iot-api-config.xml,target:${installFolder}/../../conf/iot-api-config.xml,overwrite:true);\
diff --git a/features/apimgt-extensions/pom.xml b/features/apimgt-extensions/pom.xml
index 22f08a718bd..b3d333709f6 100644
--- a/features/apimgt-extensions/pom.xml
+++ b/features/apimgt-extensions/pom.xml
@@ -37,6 +37,7 @@
org.wso2.carbon.apimgt.webapp.publisher.feature
org.wso2.carbon.apimgt.application.extension.feature
+ org.wso2.carbon.apimgt.handler.server.feature
diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/.cdm-config.xml.swp b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/.cdm-config.xml.swp
deleted file mode 100644
index a8e6a11569a..00000000000
Binary files a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/.cdm-config.xml.swp and /dev/null differ
diff --git a/pom.xml b/pom.xml
index 3932c83da8f..e48e296762a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -314,6 +314,12 @@
org.wso2.carbon.apimgt.application.extension.api
${carbon.device.mgt.version}
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.apimgt.handlers
+ ${carbon.device.mgt.version}
+
@@ -1647,6 +1653,17 @@
jersey-core
${jersey.version}
+
+
+ org.apache.synapse
+ synapse-core
+ ${org.apache.synapse.version}
+
+
+ org.apache.ws.security.wso2
+ wss4j
+ ${org.apache.ws.security.wso2.version}
+
@@ -2038,6 +2055,10 @@
1.6.1
+
+
+ 2.1.7-wso2v7
+ 1.5.11.wso2v15