From 52407ba312122c12d432f72a52d19161aef2ed9a Mon Sep 17 00:00:00 2001 From: vigneshan Date: Mon, 11 Jan 2021 13:47:45 +0530 Subject: [PATCH] Improve sso ui-request-interceptor to update application as SaaS app --- .../request/interceptor/SsoLoginHandler.java | 123 +++++++++++++++++- .../interceptor/util/HandlerConstants.java | 7 + .../request/interceptor/util/HandlerUtil.java | 39 ++++++ 3 files changed, 166 insertions(+), 3 deletions(-) diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/SsoLoginHandler.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/SsoLoginHandler.java index 620040c0d7c..0164d9f6e9c 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/SsoLoginHandler.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/SsoLoginHandler.java @@ -25,6 +25,7 @@ import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import io.entgra.ui.request.interceptor.util.HandlerConstants; import io.entgra.ui.request.interceptor.util.HandlerUtil; +import org.apache.commons.lang.text.StrSubstitutor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpHeaders; @@ -38,7 +39,9 @@ import org.apache.http.protocol.HTTP; import org.json.JSONArray; import org.json.JSONObject; import org.w3c.dom.Document; +import org.w3c.dom.NodeList; import org.wso2.carbon.device.application.mgt.common.ProxyResponse; +import org.xml.sax.InputSource; import org.xml.sax.SAXException; import javax.servlet.annotation.MultipartConfig; @@ -52,7 +55,10 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.IOException; +import java.io.StringReader; import java.util.Base64; +import java.util.HashMap; +import java.util.Map; @MultipartConfig @WebServlet("/ssoLogin") @@ -63,6 +69,7 @@ public class SsoLoginHandler extends HttpServlet { private static String adminPassword; private static String gatewayUrl; private static String iotsCoreUrl; + private static String encodedAdminCredentials; private static String encodedClientApp; private static String applicationId; private static String baseContextPath; @@ -130,7 +137,7 @@ public class SsoLoginHandler extends HttpServlet { // Register the client application HttpPost apiRegEndpoint = new HttpPost(gatewayUrl + HandlerConstants.APP_REG_ENDPOINT); - String encodedAdminCredentials = Base64.getEncoder() + encodedAdminCredentials = Base64.getEncoder() .encodeToString((adminUsername + HandlerConstants.COLON + adminPassword).getBytes()); apiRegEndpoint.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BASIC + encodedAdminCredentials); @@ -193,7 +200,8 @@ public class SsoLoginHandler extends HttpServlet { } // Update the grant types of the application - String url = iotsCoreUrl + HandlerConstants.APIM_APPLICATIONS_ENDPOINT + applicationId + "/keys/PRODUCTION"; + String url = iotsCoreUrl + HandlerConstants.APIM_APPLICATIONS_ENDPOINT + applicationId + "/keys/" + + HandlerConstants.PRODUCTION_KEY; HttpPut updateApplicationGrantTypesEndpoint = new HttpPut(url); updateApplicationGrantTypesEndpoint.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + getAccessToken(resp, encodedClientApp)); @@ -202,6 +210,9 @@ public class SsoLoginHandler extends HttpServlet { ProxyResponse updateApplicationGrantTypesEndpointResponse = HandlerUtil.execute(updateApplicationGrantTypesEndpoint); + // Update app as a SaaS app + this.updateSaasApp(applicationName); + if (updateApplicationGrantTypesEndpointResponse.getCode() == HttpStatus.SC_UNAUTHORIZED) { HandlerUtil.handleError(resp, updateApplicationGrantTypesEndpointResponse); return; @@ -216,7 +227,9 @@ public class SsoLoginHandler extends HttpServlet { log.error("Error occurred while sending the response into the socket. ", e); } catch (JsonSyntaxException e) { log.error("Error occurred while parsing the response. ", e); - } catch (ParserConfigurationException | SAXException e) { + } catch (ParserConfigurationException e) { + log.error("Error while creating the document builder."); + } catch ( SAXException e) { log.error("Error while parsing xml file.", e); } } @@ -288,4 +301,108 @@ public class SsoLoginHandler extends HttpServlet { JsonObject jTokenResultAsJsonObject = jTokenResult.getAsJsonObject(); return jTokenResultAsJsonObject.get("access_token").getAsString(); } + + /*** + * Updates Application + * + * @param appName - Application name + * @throws IOException IO exception throws if an error occurred when invoking token endpoint + * @throws ParserConfigurationException,SAXException throws if an error occurred when parsing xml + */ + private void updateSaasApp(String appName) throws ParserConfigurationException, IOException, SAXException { + File getAppRequestXmlFile = new File(HandlerConstants.PAYLOADS_DIR + "/get-app-request.xml"); + String identityAppMgtUrl = iotsCoreUrl + HandlerConstants.IDENTITY_APP_MGT_ENDPOINT;; + + HttpPost getApplicationEndpoint = new HttpPost(identityAppMgtUrl); + getApplicationEndpoint.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BASIC + + encodedAdminCredentials); + getApplicationEndpoint.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.TEXT_XML.toString()); + getApplicationEndpoint.setHeader(HandlerConstants.SOAP_ACTION_HEADER, "urn:getApplication"); + + String requestBodyString = HandlerUtil.xmlToString(getAppRequestXmlFile); + + Map data = new HashMap<>(); + appName = adminUsername + HandlerConstants.UNDERSCORE + appName + HandlerConstants.UNDERSCORE + + HandlerConstants.PRODUCTION_KEY; + data.put("applicationName", appName); + requestBodyString = StrSubstitutor.replace(requestBodyString, data); + getApplicationEndpoint.setEntity(new StringEntity(requestBodyString, ContentType.TEXT_XML)); + + ProxyResponse getApplicationEndpointResponse = HandlerUtil.execute(getApplicationEndpoint); + + Document doc = DocumentBuilderFactory.newInstance() + .newDocumentBuilder() + .parse(new InputSource(new StringReader(getApplicationEndpointResponse.getData()))); + NodeList nodeList = doc.getElementsByTagName(HandlerConstants.AX_PREFIX + "inboundAuthenticationConfig"); + NodeList childNodeList; + String nodeName; + + data.clear(); + data.put("applicationId", doc.getElementsByTagName(HandlerConstants.AX_PREFIX + "applicationID").item(0).getTextContent()); + data.put("applicationName", doc.getElementsByTagName(HandlerConstants.AX_PREFIX + "applicationName").item(0).getTextContent()); + data.put("description", doc.getElementsByTagName(HandlerConstants.AX_PREFIX + "description").item(0).getTextContent()); + data.put("saasApp", "true"); + + for (int i = 0; i < nodeList.getLength(); i++) { + childNodeList = nodeList.item(i).getChildNodes(); + for (int j = 0; j < childNodeList.getLength(); j++) { + if (childNodeList.item(j).getNodeName().equalsIgnoreCase(HandlerConstants.AX_PREFIX + "inboundAuthenticationRequestConfigs")) { + NodeList inboundAuthRequestConfigs = childNodeList.item(j).getChildNodes(); + for (int k = 0; k < inboundAuthRequestConfigs.getLength(); k++) { + nodeName = inboundAuthRequestConfigs.item(k).getNodeName(); + if (nodeName.equalsIgnoreCase(HandlerConstants.AX_PREFIX + "inboundAuthKey")) { + data.put("inboundAuthKey", inboundAuthRequestConfigs.item(k).getTextContent()); + } + if (nodeName.equalsIgnoreCase(HandlerConstants.AX_PREFIX + "inboundAuthType")) { + data.put("inboundAuthType", inboundAuthRequestConfigs.item(k).getTextContent()); + } + if (nodeName.equalsIgnoreCase(HandlerConstants.AX_PREFIX + "inboundConfigType")) { + data.put("inboundConfigType", inboundAuthRequestConfigs.item(k).getTextContent()); + } + } + } + } + } + + nodeList = doc.getElementsByTagName(HandlerConstants.AX_PREFIX + "owner"); + for (int i = 0; i < nodeList.getLength(); i++) { + childNodeList = nodeList.item(i).getChildNodes(); + for (int j = 0; j < childNodeList.getLength(); j++) { + switch (childNodeList.item(j).getNodeName()) { + case HandlerConstants.AX_PREFIX + "tenantDomain": + data.put("tenantDomain", childNodeList.item(j).getTextContent()); + break; + case HandlerConstants.AX_PREFIX + "userName": + data.put("userName", childNodeList.item(j).getTextContent()); + break; + case HandlerConstants.AX_PREFIX + "userStoreDomain": + data.put("userStoreDomain", childNodeList.item(j).getTextContent()); + break; + } + } + } + + nodeList = doc.getElementsByTagName(HandlerConstants.AX_PREFIX + "spProperties"); + for (int k = 0; k < nodeList.getLength(); k++) { + childNodeList = nodeList.item(k).getChildNodes(); + for (int l = 0; l < childNodeList.getLength(); l++) { + if (childNodeList.item(l).getNodeName().equalsIgnoreCase(HandlerConstants.AX_PREFIX + "value")) { + data.put("displayName", childNodeList.item(l).getTextContent()); + } + } + } + + File appUpdateRequest = new File(HandlerConstants.PAYLOADS_DIR + "/update-app-request.xml"); + String docStr = HandlerUtil.xmlToString(appUpdateRequest); + requestBodyString = StrSubstitutor.replace(docStr, data); + + HttpPost updateApplicationEndpoint = new HttpPost(identityAppMgtUrl); + updateApplicationEndpoint.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BASIC + + encodedAdminCredentials); + updateApplicationEndpoint.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.TEXT_XML.toString()); + updateApplicationEndpoint.setHeader(HandlerConstants.SOAP_ACTION_HEADER, "urn:updateApplication"); + updateApplicationEndpoint.setEntity(new StringEntity(requestBodyString, ContentType.TEXT_XML)); + + HandlerUtil.execute(updateApplicationEndpoint); + } } diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java index 1efcb84f955..22af32df094 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerConstants.java @@ -26,6 +26,7 @@ public class HandlerConstants { public static final String INTROSPECT_ENDPOINT = "/oauth2/introspect"; public static final String AUTHORIZATION_ENDPOINT = "/oauth2/authorize"; public static final String APIM_APPLICATIONS_ENDPOINT = "/api/am/store/v0.12/applications/"; + public static final String IDENTITY_APP_MGT_ENDPOINT = "/services/IdentityApplicationManagementService.IdentityApplicationManagementServiceHttpsSoap11Endpoint"; public static final String LOGIN_PAGE = "/login"; public static final String SSO_LOGIN_CALLBACK = "/ssoLoginCallback"; public static final String BASIC = "Basic "; @@ -53,13 +54,19 @@ public class HandlerConstants { public static final String REFRESH_TOKEN_GRANT_TYPE = "refresh_token"; public static final String PASSWORD_GRANT_TYPE = "password"; public static final String JWT_BEARER_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer"; + public static final String PRODUCTION_KEY = "PRODUCTION"; public static final String SCHEME_SEPARATOR = "://"; public static final String COLON = ":"; public static final String HTTP_PROTOCOL = "http"; + public static final String UNDERSCORE = "_"; public static final int INTERNAL_ERROR_CODE = 500; public static final long TIMEOUT = 1200; public static final String OTP_HEADER = "one-time-token"; + + public static final String AX_PREFIX = "ax2317:"; + public static final String PAYLOADS_DIR = "repository/resources/payloads"; + public static final String SOAP_ACTION_HEADER = "SOAPAction"; } diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerUtil.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerUtil.java index 5c80a88eb04..56d8ead6f82 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerUtil.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/util/HandlerUtil.java @@ -23,6 +23,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -36,17 +37,26 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.serialize.XMLSerializer; import org.json.JSONException; import org.json.JSONObject; +import org.w3c.dom.Document; import org.wso2.carbon.device.application.mgt.common.ProxyResponse; +import org.xml.sax.SAXException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; +import java.io.StringWriter; public class HandlerUtil { @@ -362,4 +372,33 @@ public class HandlerUtil { return null; } } + + /*** + * Converts xml file into string. + * + * @param xmlFile - xmlFile which needs to be converted into string. + * @return string value of the xml file. + */ + public static String xmlToString(File xmlFile) { + String stringOutput = null; + + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(xmlFile); + OutputFormat format = new OutputFormat(doc); + StringWriter stringWriterOutput = new StringWriter(); + XMLSerializer serial = new XMLSerializer(stringWriterOutput, format); + serial.serialize(doc); + stringOutput = stringWriterOutput.toString(); + } catch (IOException e) { + log.error("Error occurred while sending the response into the socket. ", e); + } catch (ParserConfigurationException e) { + log.error("Error while creating the document builder."); + } catch ( SAXException e) { + log.error("Error while parsing xml file.", e); + } + + return stringOutput; + } }