From 0e4234db97ee3ce48c48a498aeee42ecd98e7233 Mon Sep 17 00:00:00 2001 From: Madawa Soysa Date: Mon, 17 Jun 2019 16:32:55 +1000 Subject: [PATCH 1/5] Retrieve session auth data from the header value X-Platform Fixes entgra/product-iots#110 Related to entgra/product-iots#103 --- .../request/interceptor/InvokerHandler.java | 66 +++++++++---------- .../interceptor/util/HandlerConstants.java | 4 +- 2 files changed, 32 insertions(+), 38 deletions(-) diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java index 1dd968ecd5..124f1e5c4c 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java @@ -63,22 +63,11 @@ import static io.entgra.ui.request.interceptor.util.HandlerUtil.execute; public class InvokerHandler extends HttpServlet { private static final Log log = LogFactory.getLog(LoginHandler.class); private static final long serialVersionUID = -6508020875358160165L; -// private static final HeaderGroup nonForwardingHeaders = new HeaderGroup(); private static AuthData authData; private static String apiEndpoint; private static String serverUrl; private static String platform; -// static { -// // Initializing hop-by-hop headers to omit them from forwarding to the backend -// String[] headers = {HttpHeaders.CONNECTION, HttpHeaders.TRANSFER_ENCODING, HttpHeaders.PROXY_AUTHENTICATE, -// HttpHeaders.PROXY_AUTHORIZATION, HttpHeaders.UPGRADE, HttpHeaders.TE, HttpHeaders.TRAILER, -// HandlerConstants.KEEP_ALIVE, HandlerConstants.PUBLIC}; -// for (String header : headers) { -// nonForwardingHeaders.addHeader(new BasicHeader(header, null)); -// } -// } - @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) { try { @@ -221,6 +210,7 @@ public class InvokerHandler extends HttpServlet { } } } + /*** * * @param req {@link HttpServletRequest} @@ -232,35 +222,32 @@ public class InvokerHandler extends HttpServlet { throws IOException { serverUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort(); apiEndpoint = req.getPathInfo(); + String sessionAuthDataKey = req.getHeader(HandlerConstants.X_PLATFORM_HEADER); HttpSession session = req.getSession(false); if (session == null) { log.error("Unauthorized, You are not logged in. Please log in to the portal"); - ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED); - proxyResponse.setExecutorResponse( - HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED)); - HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); + handleError(req, resp, HttpStatus.SC_UNAUTHORIZED); + return false; + } + + if (StringUtils.isEmpty(sessionAuthDataKey)) { + log.error("\"X-Platform\" header is empty in the request. Header is required to obtain the auth data from" + + " session."); + handleError(req, resp, HttpStatus.SC_BAD_REQUEST); return false; } - authData = (AuthData) session.getAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY); + + authData = (AuthData) session.getAttribute(sessionAuthDataKey); platform = (String) session.getAttribute(HandlerConstants.PLATFORM); if (authData == null) { log.error("Unauthorized, Access token not found in the current session"); - ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED); - proxyResponse.setExecutorResponse( - HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED)); - HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); + handleError(req, resp, HttpStatus.SC_UNAUTHORIZED); return false; } if (apiEndpoint == null || req.getMethod() == null) { log.error("Bad Request, Either destination api-endpoint or method is empty"); - ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_BAD_REQUEST); - proxyResponse.setExecutorResponse( - HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_BAD_REQUEST)); - HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); + handleError(req, resp, HttpStatus.SC_BAD_REQUEST); return false; } return true; @@ -307,11 +294,7 @@ public class InvokerHandler extends HttpServlet { HttpSession session = req.getSession(false); if (session == null) { log.error("Couldn't find a session, hence it is required to login and proceed."); - ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED); - proxyResponse.setExecutorResponse( - HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED)); - HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); + handleError(req, resp, HttpStatus.SC_UNAUTHORIZED); return false; } @@ -352,11 +335,24 @@ public class InvokerHandler extends HttpServlet { } log.error("Error Occurred in token renewal process."); + handleError(req, resp, HttpStatus.SC_INTERNAL_SERVER_ERROR); + return false; + } + + /** + * Handle error requests + * + * @param req {@link HttpServletRequest} + * @param resp {@link HttpServletResponse} + * @param errorCode HTTP error status code + * @throws IOException If error occurred when trying to send the error response. + */ + private static void handleError(HttpServletRequest req, HttpServletResponse resp, int errorCode) + throws IOException { ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR); + proxyResponse.setCode(errorCode); proxyResponse.setExecutorResponse( - HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_INTERNAL_SERVER_ERROR)); + HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(errorCode)); HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); - return false; } } 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 aa80d7fd66..4a790f18e9 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 @@ -23,8 +23,7 @@ public class HandlerConstants { public static final String APP_REG_ENDPOINT = "/api-application-registration/register"; public static final String UI_CONFIG_ENDPOINT = "/api/application-mgt/v1.0/config/ui-config"; public static final String TOKEN_ENDPOINT = "/oauth2/token"; - public static final String PUBLIC = "Public"; - public static final String KEEP_ALIVE = "Keep-Alive"; + public static final String X_PLATFORM_HEADER = "X-Platform"; public static final String BASIC = "Basic "; public static final String BEARER = "Bearer "; public static final String COLON = ":"; @@ -33,7 +32,6 @@ public class HandlerConstants { public static final String SESSION_AUTH_DATA_KEY = "application-mgt"; public static final String UI_CONFIG_KEY = "ui-config"; public static final String PLATFORM = "platform"; - public static final String SERVER_HOST = "server-host"; public static final String DEFAULT_ERROR_CALLBACK = "/pages/error/default"; public static final String LOGIN_RESPONSE_KEY = "loginResponse"; public static final String FAILURE_CALLBACK_KEY = "failureCallback"; From a8843711e0a74400b691ac6e2009a862d92eb1de Mon Sep 17 00:00:00 2001 From: Madawa Soysa Date: Fri, 21 Jun 2019 15:11:01 +1000 Subject: [PATCH 2/5] Fix issue with auth data persistence key This commit changes the auth data persistance key to the value of platform instead of using a hard coded constant. Fixes entgra/product-iots#110 Related to entgra/product-iots#103 --- .../java/io/entgra/ui/request/interceptor/LoginHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java index 5f1167073d..25516268c6 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java @@ -196,7 +196,7 @@ public class LoginHandler extends HttpServlet { authData.setAccessToken(jTokenResultAsJsonObject.get("access_token").getAsString()); authData.setRefreshToken(jTokenResultAsJsonObject.get("refresh_token").getAsString()); authData.setScope(jTokenResultAsJsonObject.get("scope").getAsString()); - session.setAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY, authData); + session.setAttribute(platform, authData); return true; } From cd9e3e52ed5f789397e697b0b3cbc7bd634e0e66 Mon Sep 17 00:00:00 2001 From: Madawa Soysa Date: Fri, 21 Jun 2019 15:13:08 +1000 Subject: [PATCH 3/5] Implement multipart request handling through invoker This commit improves the Invoker handler to handle multi part requests by generating the proxy request body using the body of the incoming multi part requests. Fixes entgra/product-iots#111 Related to entgra/product-iots#103 --- .../ApplicationManagementPublisherAPI.java | 12 +- ...ApplicationManagementPublisherAPIImpl.java | 12 +- .../io.entgra.ui.request.interceptor/pom.xml | 5 + .../request/interceptor/InvokerHandler.java | 119 +++++++++++++----- .../interceptor/util/HandlerConstants.java | 3 +- pom.xml | 6 + 6 files changed, 112 insertions(+), 45 deletions(-) diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java index 99355e5c96..699a97f78a 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java @@ -273,7 +273,7 @@ public interface ApplicationManagementPublisherAPI { @POST @Path("/ent-app") @Produces(MediaType.APPLICATION_JSON) - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @ApiOperation( consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, @@ -342,7 +342,7 @@ public interface ApplicationManagementPublisherAPI { @POST @Path("/web-app") @Produces(MediaType.APPLICATION_JSON) - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @ApiOperation( consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, @@ -406,7 +406,7 @@ public interface ApplicationManagementPublisherAPI { @POST @Path("/public-app") @Produces(MediaType.APPLICATION_JSON) - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @ApiOperation( consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, @@ -467,7 +467,7 @@ public interface ApplicationManagementPublisherAPI { @POST @Produces(MediaType.APPLICATION_JSON) - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @Path("/ent-app/{appId}") @ApiOperation( consumes = MediaType.APPLICATION_JSON, @@ -583,7 +583,7 @@ public interface ApplicationManagementPublisherAPI { @PUT @Path("/image-artifacts/{uuid}") @Produces(MediaType.APPLICATION_JSON) - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @ApiOperation( consumes = MediaType.MULTIPART_FORM_DATA, produces = MediaType.APPLICATION_JSON, @@ -653,7 +653,7 @@ public interface ApplicationManagementPublisherAPI { @PUT @Path("/app-artifacts/{deviceType}/{appType}/{appId}/{uuid}") @Produces(MediaType.APPLICATION_JSON) - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @ApiOperation( consumes = MediaType.MULTIPART_FORM_DATA, produces = MediaType.APPLICATION_JSON, diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java index d0d091df03..f3669c0979 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.api/src/main/java/org/wso2/carbon/device/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java @@ -164,7 +164,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } @POST - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @Path("/ent-app") public Response createEntApp( @Multipart("application") ApplicationWrapper applicationWrapper, @@ -204,7 +204,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } @POST - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @Path("/web-app") public Response createWebApp( @Multipart("webapp") WebAppWrapper webAppWrapper, @@ -242,7 +242,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } @POST - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @Path("/public-app") public Response createPubApp( @Multipart("public-app") PublicAppWrapper publicAppWrapper, @@ -280,7 +280,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } @POST - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @Path("/ent-app/{appId}") public Response createEntAppRelease( @PathParam("appId") int appId, @@ -320,7 +320,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem @Override @PUT - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @Produces(MediaType.APPLICATION_JSON) @Path("/image-artifacts/{uuid}") public Response updateApplicationImageArtifacts( @@ -357,7 +357,7 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem @Override @PUT - @Consumes("multipart/mixed") + @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) @Path("/app-artifact/{deviceType}/{appType}/{uuid}") public Response updateApplicationArtifact( @PathParam("deviceType") String deviceType, diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/pom.xml b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/pom.xml index 2fe4013823..d2cc394427 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/pom.xml +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/pom.xml @@ -151,5 +151,10 @@ org.wso2.carbon.device.application.mgt.common provided + + org.apache.httpcomponents + httpmime + compile + \ No newline at end of file diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java index 124f1e5c4c..864f5d6801 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java @@ -24,12 +24,17 @@ import com.google.gson.JsonParser; import io.entgra.ui.request.interceptor.beans.AuthData; import io.entgra.ui.request.interceptor.util.HandlerConstants; import io.entgra.ui.request.interceptor.util.HandlerUtil; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpHeaders; import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; @@ -38,6 +43,9 @@ import org.apache.http.cookie.SM; import org.apache.http.entity.ContentType; import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.entity.mime.content.InputStreamBody; import org.wso2.carbon.device.application.mgt.common.ProxyResponse; import javax.servlet.annotation.MultipartConfig; @@ -48,6 +56,7 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.Enumeration; +import java.util.List; import static io.entgra.ui.request.interceptor.util.HandlerUtil.execute; @@ -61,25 +70,19 @@ import static io.entgra.ui.request.interceptor.util.HandlerUtil.execute; } ) public class InvokerHandler extends HttpServlet { - private static final Log log = LogFactory.getLog(LoginHandler.class); + private static final Log log = LogFactory.getLog(InvokerHandler.class); private static final long serialVersionUID = -6508020875358160165L; - private static AuthData authData; - private static String apiEndpoint; - private static String serverUrl; - private static String platform; + private AuthData authData; + private String apiEndpoint; + private String serverUrl; + private String platform; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) { try { if (validateRequest(req, resp)) { HttpPost postRequest = new HttpPost(generateBackendRequestURL(req)); - if (StringUtils.isNotEmpty(req.getHeader(HttpHeaders.CONTENT_LENGTH)) || - StringUtils.isNotEmpty(req.getHeader(HttpHeaders.TRANSFER_ENCODING))) { - InputStreamEntity entity = new InputStreamEntity(req.getInputStream(), - Long.parseLong(req.getHeader(HttpHeaders.CONTENT_LENGTH))); - postRequest.setEntity(entity); - } - copyRequestHeaders(req, postRequest); + generateRequestEntity(req, postRequest); postRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); ProxyResponse proxyResponse = execute(postRequest); @@ -96,6 +99,8 @@ public class InvokerHandler extends HttpServlet { } HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse); } + } catch (FileUploadException e) { + log.error("Error occurred when processing Multipart POST request.", e); } catch (IOException e) { log.error("Error occurred when processing POST request.", e); } @@ -106,7 +111,7 @@ public class InvokerHandler extends HttpServlet { try { if (validateRequest(req, resp)) { HttpGet getRequest = new HttpGet(generateBackendRequestURL(req)); - copyRequestHeaders(req, getRequest); + copyRequestHeaders(req, getRequest, false); getRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); ProxyResponse proxyResponse = execute(getRequest); if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) { @@ -132,14 +137,7 @@ public class InvokerHandler extends HttpServlet { try { if (validateRequest(req, resp)) { HttpPut putRequest = new HttpPut(generateBackendRequestURL(req)); - if ((StringUtils.isNotEmpty(req.getHeader(HttpHeaders.CONTENT_LENGTH)) && - Double.parseDouble(req.getHeader(HttpHeaders.CONTENT_LENGTH)) > 0) || - StringUtils.isNotEmpty(req.getHeader(HttpHeaders.TRANSFER_ENCODING))) { - InputStreamEntity entity = new InputStreamEntity(req.getInputStream(), - Long.parseLong(req.getHeader(HttpHeaders.CONTENT_LENGTH))); - putRequest.setEntity(entity); - } - copyRequestHeaders(req, putRequest); + generateRequestEntity(req, putRequest); putRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); ProxyResponse proxyResponse = execute(putRequest); @@ -156,6 +154,8 @@ public class InvokerHandler extends HttpServlet { } HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse); } + } catch (FileUploadException e) { + log.error("Error occurred when processing Multipart PUT request.", e); } catch (IOException e) { log.error("Error occurred when processing PUT request.", e); } @@ -166,7 +166,7 @@ public class InvokerHandler extends HttpServlet { try { if (validateRequest(req, resp)) { HttpDelete deleteRequest = new HttpDelete(generateBackendRequestURL(req)); - copyRequestHeaders(req, deleteRequest); + copyRequestHeaders(req, deleteRequest, false); deleteRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); ProxyResponse proxyResponse = execute(deleteRequest); if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) { @@ -187,6 +187,49 @@ public class InvokerHandler extends HttpServlet { } } + /** + * Generate te request entity for POST and PUT requests from the incoming request. + * + * @param req incoming {@link HttpServletRequest}. + * @param proxyRequest proxy request instance. + * @throws FileUploadException If unable to parse the incoming request for multipart content extraction. + * @throws IOException If error occurred while generating the request body. + */ + private void generateRequestEntity(HttpServletRequest req, HttpEntityEnclosingRequestBase proxyRequest) + throws FileUploadException, IOException { + if (ServletFileUpload.isMultipartContent(req)) { + ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory()); + List fileItemList = servletFileUpload.parseRequest(req); + MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); + entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); + for (FileItem item : fileItemList) { + if (!item.isFormField()) { + entityBuilder.addPart(item.getFieldName(), new InputStreamBody(item.getInputStream(), + ContentType.create(item.getContentType()), item.getName())); + } else { + entityBuilder.addTextBody(item.getFieldName(), item.getString(), + ContentType.create(item.getContentType())); + } + } + proxyRequest.setEntity(entityBuilder.build()); + copyRequestHeaders(req, proxyRequest, false); + } else { + if (StringUtils.isNotEmpty(req.getHeader(HttpHeaders.CONTENT_LENGTH)) || + StringUtils.isNotEmpty(req.getHeader(HttpHeaders.TRANSFER_ENCODING))) { + InputStreamEntity entity = new InputStreamEntity(req.getInputStream(), + Long.parseLong(req.getHeader(HttpHeaders.CONTENT_LENGTH))); + proxyRequest.setEntity(entity); + } + copyRequestHeaders(req, proxyRequest, true); + } + } + + /** + * Generates the target URL for the proxy request. + * + * @param req incoming {@link HttpServletRequest} + * @return Target URL + */ private String generateBackendRequestURL(HttpServletRequest req) { StringBuilder urlBuilder = new StringBuilder(); urlBuilder.append(serverUrl).append(HandlerConstants.API_COMMON_CONTEXT).append(apiEndpoint); @@ -196,12 +239,22 @@ public class InvokerHandler extends HttpServlet { return urlBuilder.toString(); } - private void copyRequestHeaders(HttpServletRequest req, HttpRequestBase httpRequest) { + /** + * Copy incoming request headers to the proxy request. + * + * @param req incoming {@link HttpServletRequest} + * @param httpRequest proxy request instance. + * @param preserveContentType true if content type header needs to be preserved. + * This should be set to false when handling multipart requests as Http + * client will generate the Content-Type header automatically. + */ + private void copyRequestHeaders(HttpServletRequest req, HttpRequestBase httpRequest, boolean preserveContentType) { Enumeration headerNames = req.getHeaderNames(); while (headerNames.hasMoreElements()) { String headerName = headerNames.nextElement(); if (headerName.equalsIgnoreCase(HttpHeaders.CONTENT_LENGTH) || - headerName.equalsIgnoreCase(SM.COOKIE)) { + headerName.equalsIgnoreCase(SM.COOKIE) || + (!preserveContentType && headerName.equalsIgnoreCase(HttpHeaders.CONTENT_TYPE))) { continue; } Enumeration headerValues = req.getHeaders(headerName); @@ -212,33 +265,35 @@ public class InvokerHandler extends HttpServlet { } /*** + * Validates the incoming request. * * @param req {@link HttpServletRequest} * @param resp {@link HttpServletResponse} * @return If request is a valid one, returns TRUE, otherwise return FALSE * @throws IOException If and error occurs while witting error response to client side */ - private static boolean validateRequest(HttpServletRequest req, HttpServletResponse resp) + private boolean validateRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException { serverUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort(); apiEndpoint = req.getPathInfo(); - String sessionAuthDataKey = req.getHeader(HandlerConstants.X_PLATFORM_HEADER); + platform = req.getHeader(HandlerConstants.X_PLATFORM_HEADER); HttpSession session = req.getSession(false); + if (session == null) { log.error("Unauthorized, You are not logged in. Please log in to the portal"); handleError(req, resp, HttpStatus.SC_UNAUTHORIZED); return false; } - if (StringUtils.isEmpty(sessionAuthDataKey)) { + if (StringUtils.isEmpty(platform)) { log.error("\"X-Platform\" header is empty in the request. Header is required to obtain the auth data from" + " session."); handleError(req, resp, HttpStatus.SC_BAD_REQUEST); return false; } - authData = (AuthData) session.getAttribute(sessionAuthDataKey); - platform = (String) session.getAttribute(HandlerConstants.PLATFORM); + authData = (AuthData) session.getAttribute(platform); + if (authData == null) { log.error("Unauthorized, Access token not found in the current session"); handleError(req, resp, HttpStatus.SC_UNAUTHORIZED); @@ -262,7 +317,7 @@ public class InvokerHandler extends HttpServlet { * @return {@link ProxyResponse} if successful and null if failed. * @throws IOException If an error occurs when try to retry the request. */ - private static ProxyResponse retryRequestWithRefreshedToken(HttpServletRequest req, HttpServletResponse resp, + private ProxyResponse retryRequestWithRefreshedToken(HttpServletRequest req, HttpServletResponse resp, HttpRequestBase httpRequest) throws IOException { if (refreshToken(req, resp)) { httpRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); @@ -284,7 +339,7 @@ public class InvokerHandler extends HttpServlet { * @return If successfully renew tokens, returns TRUE otherwise return FALSE * @throws IOException If an error occurs while witting error response to client side or invoke token renewal API */ - private static boolean refreshToken(HttpServletRequest req, HttpServletResponse resp) + private boolean refreshToken(HttpServletRequest req, HttpServletResponse resp) throws IOException { if (log.isDebugEnabled()) { log.debug("refreshing the token"); @@ -347,7 +402,7 @@ public class InvokerHandler extends HttpServlet { * @param errorCode HTTP error status code * @throws IOException If error occurred when trying to send the error response. */ - private static void handleError(HttpServletRequest req, HttpServletResponse resp, int errorCode) + private void handleError(HttpServletRequest req, HttpServletResponse resp, int errorCode) throws IOException { ProxyResponse proxyResponse = new ProxyResponse(); proxyResponse.setCode(errorCode); 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 4a790f18e9..cf2cb4db60 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 @@ -23,7 +23,6 @@ public class HandlerConstants { public static final String APP_REG_ENDPOINT = "/api-application-registration/register"; public static final String UI_CONFIG_ENDPOINT = "/api/application-mgt/v1.0/config/ui-config"; public static final String TOKEN_ENDPOINT = "/oauth2/token"; - public static final String X_PLATFORM_HEADER = "X-Platform"; public static final String BASIC = "Basic "; public static final String BEARER = "Bearer "; public static final String COLON = ":"; @@ -39,6 +38,8 @@ public class HandlerConstants { public static final String EXECUTOR_EXCEPTION_PREFIX = "ExecutorException-"; public static final String TOKEN_IS_EXPIRED = "ACCESS_TOKEN_IS_EXPIRED"; + public static final String X_PLATFORM_HEADER = "X-Platform"; + public static final int INTERNAL_ERROR_CODE = 500; public static final long TIMEOUT = 1200; } diff --git a/pom.xml b/pom.xml index f3b33c70e1..736ce68f98 100644 --- a/pom.xml +++ b/pom.xml @@ -1310,6 +1310,11 @@ httpcore ${apache.http.core.version} + + org.apache.httpcomponents + httpmime + ${apache.http.mime.version} + commons-lang.wso2 commons-lang @@ -2137,6 +2142,7 @@ 4.5.6 4.4.10 + 4.5.8 1.9 From aaf4e5dcf203b4e5ca8496c43d10096930735c39 Mon Sep 17 00:00:00 2001 From: Madawa Soysa Date: Fri, 21 Jun 2019 16:21:04 +1000 Subject: [PATCH 4/5] Remove older App Mgt handler source Related to entgra/product-iots#103 --- .../pom.xml | 155 --------- .../mgt/handler/InvokerHandler.java | 239 -------------- .../application/mgt/handler/LoginHandler.java | 293 ------------------ .../mgt/handler/beans/AuthData.java | 88 ------ .../handler/exceptions/LoginException.java | 38 --- .../mgt/handler/util/HandlerConstants.java | 44 --- .../mgt/handler/util/HandlerUtil.java | 241 -------------- .../webapp/META-INF/webapp-classloading.xml | 35 --- .../src/main/webapp/WEB-INF/web.xml | 103 ------ components/application-mgt/pom.xml | 1 - 10 files changed, 1237 deletions(-) delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.handler/pom.xml delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/InvokerHandler.java delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/LoginHandler.java delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/beans/AuthData.java delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/exceptions/LoginException.java delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/util/HandlerConstants.java delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/util/HandlerUtil.java delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/webapp/META-INF/webapp-classloading.xml delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/webapp/WEB-INF/web.xml diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/pom.xml b/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/pom.xml deleted file mode 100644 index 14560dc723..0000000000 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/pom.xml +++ /dev/null @@ -1,155 +0,0 @@ - - - - 4.0.0 - - - org.wso2.carbon.devicemgt - application-mgt - 3.2.7-SNAPSHOT - - - org.wso2.carbon.device.application.mgt.handler - 3.2.7-SNAPSHOT - war - WSO2 Carbon - Application Management Authentication Handler API - Proxy Service for Authentication Handling in WSO2 App Manager. - http://wso2.org - - - - - maven-war-plugin - - WEB-INF/lib/*cxf*.jar - api#application-mgt-handler#v1.0 - - - - - - - - deploy - - compile - - - org.apache.maven.plugins - maven-antrun-plugin - 1.7 - - - compile - - run - - - - - - - - - - - - - - - - - - client - - test - - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - - - test - - java - - - - - - - - - - - - org.apache.cxf - cxf-rt-frontend-jaxws - provided - - - org.apache.cxf - cxf-rt-frontend-jaxrs - provided - - - org.apache.cxf - cxf-rt-transports-http - provided - - - javax.servlet - javax.servlet-api - provided - - - junit - junit - test - - - commons-logging - commons-logging - - - - org.apache.httpcomponents - httpclient - - - - - org.apache.httpcomponents - httpcore - - - org.wso2.carbon.devicemgt - org.wso2.carbon.device.application.mgt.core - provided - - - org.wso2.carbon.devicemgt - org.wso2.carbon.device.application.mgt.common - provided - - - diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/InvokerHandler.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/InvokerHandler.java deleted file mode 100644 index e98346130f..0000000000 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/InvokerHandler.java +++ /dev/null @@ -1,239 +0,0 @@ -/* Copyright (c) 2018, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. - * - * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -package org.wso2.carbon.device.application.mgt.handler; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.wso2.carbon.device.application.mgt.common.ProxyResponse; -import org.wso2.carbon.device.application.mgt.handler.beans.AuthData; -import org.wso2.carbon.device.application.mgt.handler.util.HandlerConstants; -import org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil; - -import javax.servlet.annotation.MultipartConfig; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.IOException; - -import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; -import static org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil.execute; - -@MultipartConfig -@WebServlet("/invoke") -public class InvokerHandler extends HttpServlet { - private static final Log log = LogFactory.getLog(LoginHandler.class); - private static final long serialVersionUID = -6508020875358160165L; - private static AuthData authData; - private static String apiEndpoint; - private static String method; - private static String serverUrl; - private static String platform; - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) { - try { - if (!validateRequest(req, resp)) { - return; - } - HttpRequestBase executor = constructExecutor(req); - if (executor == null) { - resp.sendError(HTTP_BAD_REQUEST, "Bad Request, method: " + method + " is not supported"); - return; - } - executor.setHeader(HandlerConstants.AUTHORIZATION_HEADER_KEY, "Bearer " + authData.getAccessToken()); - ProxyResponse proxyResponse = execute(executor); - - if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) { - if (!refreshToken(req, resp)) { - return; - } - executor.setHeader(HandlerConstants.AUTHORIZATION_HEADER_KEY, "Bearer " + authData.getAccessToken()); - proxyResponse = execute(executor); - if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { - log.error("Error occurred while invoking the API after refreshing the token."); - HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); - return; - } - } - if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { - log.error("Error occurred while invoking the API endpoint."); - HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); - return; - } - HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse); - } catch (IOException e) { - log.error("Error occured when processing invoke call.", e); - } - } - - /*** - * - * @param req {@link HttpServletRequest} - * @return {@link HttpRequestBase} if method equals to either GET, POST, PUT or DELETE otherwise returns NULL. - */ - private HttpRequestBase constructExecutor(HttpServletRequest req) { - String payload = req.getParameter("payload"); - String contentType = req.getParameter("content-type"); - if (contentType == null || contentType.isEmpty()) { - contentType = ContentType.APPLICATION_JSON.toString(); - } - - HttpRequestBase executor; - if (HttpGet.METHOD_NAME.equalsIgnoreCase(method)) { - executor = new HttpGet(serverUrl + HandlerConstants.API_COMMON_CONTEXT + apiEndpoint); - } else if (HttpPost.METHOD_NAME.equalsIgnoreCase(method)) { - executor = new HttpPost(serverUrl + HandlerConstants.API_COMMON_CONTEXT + apiEndpoint); - StringEntity payloadEntity = new StringEntity(payload, ContentType.create(contentType)); - ((HttpPost) executor).setEntity(payloadEntity); - } else if (HttpPut.METHOD_NAME.equalsIgnoreCase(method)) { - executor = new HttpPut(serverUrl + HandlerConstants.API_COMMON_CONTEXT + apiEndpoint); - StringEntity payloadEntity = new StringEntity(payload, ContentType.create(contentType)); - ((HttpPut) executor).setEntity(payloadEntity); - } else if (HttpDelete.METHOD_NAME.equalsIgnoreCase(method)) { - executor = new HttpDelete(serverUrl + HandlerConstants.API_COMMON_CONTEXT + apiEndpoint); - } else { - return null; - } - return executor; - } - - /*** - * - * @param req {@link HttpServletRequest} - * @param resp {@link HttpServletResponse} - * @return If request is a valid one, returns TRUE, otherwise return FALSE - * @throws IOException If and error occurs while witting error response to client side - */ - private static boolean validateRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException { - serverUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort(); - apiEndpoint = req.getParameter("api-endpoint"); - method = req.getParameter("method"); - HttpSession session = req.getSession(false); - if (session == null) { - log.error("Unauthorized, You are not logged in. Please log in to the portal"); - ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED); - proxyResponse.setExecutorResponse( - HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED)); - HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); - return false; - } - authData = (AuthData) session.getAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY); - platform = (String) session.getAttribute(HandlerConstants.PLATFORM); - if (authData == null) { - log.error("Unauthorized, Access token couldn't found in the current session"); - ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED); - proxyResponse.setExecutorResponse( - HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED)); - HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); - return false; - } - - if (apiEndpoint == null || method == null) { - log.error("Bad Request, Either api-endpoint or method is empty"); - ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_BAD_REQUEST); - proxyResponse.setExecutorResponse( - HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_BAD_REQUEST)); - HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); - return false; - } - return true; - } - - /*** - * - * @param req {@link HttpServletRequest} - * @param resp {@link HttpServletResponse} - * @return If successfully renew tokens, returns TRUE otherwise return FALSE - * @throws IOException If and error occurs while witting error response to client side or invoke token renewal API - */ - private static boolean refreshToken(HttpServletRequest req, HttpServletResponse resp) throws IOException { - log.debug("refreshing the token"); - HttpPost tokenEndpoint = new HttpPost( - serverUrl + HandlerConstants.API_COMMON_CONTEXT + HandlerConstants.TOKEN_ENDPOINT); - HttpSession session = req.getSession(false); - if (session == null) { - log.error("Couldn't find a session, hence it is required to login and proceed."); - ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_UNAUTHORIZED); - proxyResponse.setExecutorResponse( - HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_UNAUTHORIZED)); - HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); - return false; - } - - StringEntity tokenEndpointPayload = new StringEntity( - "grant_type=refresh_token&refresh_token=" + authData.getRefreshToken() + "&scope=PRODUCTION", - ContentType.APPLICATION_FORM_URLENCODED); - - tokenEndpoint.setEntity(tokenEndpointPayload); - String encodedClientApp = authData.getEncodedClientApp(); - tokenEndpoint.setHeader("Authorization", "Basic " + encodedClientApp); - tokenEndpoint.setHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.toString()); - - ProxyResponse tokenResultResponse = execute(tokenEndpoint); - if (tokenResultResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { - log.error("Error occurred while refreshing access token."); - HandlerUtil.handleError(req, resp, serverUrl, platform, tokenResultResponse); - return false; - } - - JsonParser jsonParser = new JsonParser(); - JsonElement jTokenResult = jsonParser.parse(tokenResultResponse.getData()); - - if (jTokenResult.isJsonObject()) { - JsonObject jTokenResultAsJsonObject = jTokenResult.getAsJsonObject(); - AuthData newAuthData = new AuthData(); - - newAuthData.setAccessToken(jTokenResultAsJsonObject.get("access_token").getAsString()); - newAuthData.setRefreshToken(jTokenResultAsJsonObject.get("refresh_token").getAsString()); - newAuthData.setScope(jTokenResultAsJsonObject.get("scope").getAsString()); - newAuthData.setClientId(authData.getClientId()); - newAuthData.setClientSecret(authData.getClientSecret()); - newAuthData.setEncodedClientApp(authData.getEncodedClientApp()); - newAuthData.setUsername(authData.getUsername()); - authData = newAuthData; - session.setAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY, newAuthData); - return true; - } - - log.error("Error Occurred in token renewal process."); - ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR); - proxyResponse.setExecutorResponse( - HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_INTERNAL_SERVER_ERROR)); - HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); - return false; - } -} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/LoginHandler.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/LoginHandler.java deleted file mode 100644 index 86fae9e66b..0000000000 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/LoginHandler.java +++ /dev/null @@ -1,293 +0,0 @@ -/* Copyright (c) 2018, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. - * - * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.device.application.mgt.handler; - -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; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.protocol.HTTP; -import org.wso2.carbon.device.application.mgt.common.ProxyResponse; -import org.wso2.carbon.device.application.mgt.handler.beans.AuthData; -import org.wso2.carbon.device.application.mgt.handler.exceptions.LoginException; -import org.wso2.carbon.device.application.mgt.handler.util.HandlerConstants; -import org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil; -import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; -import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig; - -import javax.servlet.annotation.MultipartConfig; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.IOException; -import java.util.Base64; - -import static org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil.execute; - -@MultipartConfig -@WebServlet("/login") -public class LoginHandler extends HttpServlet { - private static final Log log = LogFactory.getLog(LoginHandler.class); - private static final long serialVersionUID = 9050048549140517002L; - - private static String username; - private static String password; - private static String platform; - private static String serverUrl; - private static String uiConfigUrl; - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) { - try { - validateLoginRequest(req, resp); - DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance() - .getDeviceManagementConfig(); - String adminUsername = deviceManagementConfig.getIdentityConfigurations().getAdminUsername(); - String adminPwd = deviceManagementConfig.getIdentityConfigurations().getAdminPassword(); - - HttpSession httpSession = req.getSession(false); - if (httpSession != null) { - httpSession.invalidate(); - } - httpSession = req.getSession(true); - //setting session to expiry in 5 mins - httpSession.setMaxInactiveInterval(Math.toIntExact(HandlerConstants.TIMEOUT)); - - HttpGet uiConfigEndpoint = new HttpGet(uiConfigUrl); - JsonParser jsonParser = new JsonParser(); - ProxyResponse uiConfigResponse = execute(uiConfigEndpoint); - String executorResponse = uiConfigResponse.getExecutorResponse(); - if (!StringUtils.isEmpty(executorResponse) && executorResponse - .contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { - log.error("Error occurred while getting UI configurations by invoking " + uiConfigUrl); - HandlerUtil.handleError(req, resp, serverUrl, platform, uiConfigResponse); - return; - } - - String uiConfig = uiConfigResponse.getData(); - if (uiConfig == null){ - log.error("UI config retrieval is failed, and didn't find UI configuration for App manager."); - HandlerUtil.handleError(req, resp, serverUrl, platform, null); - return; - } - JsonElement uiConfigJsonElement = jsonParser.parse(uiConfigResponse.getData()); - JsonObject uiConfigJsonObject = null; - if (uiConfigJsonElement.isJsonObject()) { - uiConfigJsonObject = uiConfigJsonElement.getAsJsonObject(); - httpSession.setAttribute(HandlerConstants.UI_CONFIG_KEY, uiConfigJsonObject); - httpSession.setAttribute(HandlerConstants.PLATFORM, serverUrl); - } - if (uiConfigJsonObject == null) { - log.error( - "Either UI config json element is not an json object or converting rom json element to json object is failed."); - HandlerUtil.handleError(req, resp, serverUrl, platform, null); - return; - } - - boolean isSsoEnable = uiConfigJsonObject.get("isSsoEnable").getAsBoolean(); - JsonArray tags = uiConfigJsonObject.get("appRegistration").getAsJsonObject().get("tags").getAsJsonArray(); - JsonArray scopes = uiConfigJsonObject.get("scopes").getAsJsonArray(); - - if (isSsoEnable) { - log.debug("SSO is enabled"); - } else { - // default login - HttpPost apiRegEndpoint = new HttpPost(serverUrl + HandlerConstants.APP_REG_ENDPOINT); - apiRegEndpoint.setHeader(HandlerConstants.AUTHORIZATION, HandlerConstants.BASIC + Base64.getEncoder() - .encodeToString((adminUsername + HandlerConstants.COLON + adminPwd).getBytes())); - apiRegEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()); - apiRegEndpoint.setEntity(constructAppRegPayload(tags)); - - ProxyResponse clientAppResponse = execute(apiRegEndpoint); - String clientAppResult = clientAppResponse.getData(); - - if (!StringUtils.isEmpty(clientAppResult) && getTokenAndPersistInSession(req, resp, - clientAppResponse.getData(), scopes)) { - ProxyResponse proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_OK); - proxyResponse.setUrl(serverUrl + "/" + platform + uiConfigJsonObject.get(HandlerConstants.LOGIN_RESPONSE_KEY) - .getAsJsonObject().get("successCallback").getAsString()); - HandlerUtil.handleSuccess(req, resp, serverUrl, platform, proxyResponse); - return; - } - HandlerUtil.handleError(req, resp, serverUrl, platform, null); - } - } catch (IOException e) { - log.error("Error occured while sending the response into the socket. ", e); - } catch (JsonSyntaxException e) { - log.error("Error occured while parsing the response. ", e); - } catch (LoginException e) { - log.error("Error occured while getting token data. ", e); - } - } - - /*** - * - * @param req - {@link HttpServletRequest} - * @param clientAppResult - clientAppResult - * @param scopes - scopes defied in the application-mgt.xml - * @throws LoginException - login exception throws when getting token result - */ - private boolean getTokenAndPersistInSession(HttpServletRequest req, HttpServletResponse resp, - String clientAppResult, JsonArray scopes) throws LoginException { - JsonParser jsonParser = new JsonParser(); - try { - JsonElement jClientAppResult = jsonParser.parse(clientAppResult); - if (jClientAppResult.isJsonObject()) { - JsonObject jClientAppResultAsJsonObject = jClientAppResult.getAsJsonObject(); - String clientId = jClientAppResultAsJsonObject.get("client_id").getAsString(); - String clientSecret = jClientAppResultAsJsonObject.get("client_secret").getAsString(); - String encodedClientApp = Base64.getEncoder() - .encodeToString((clientId + ":" + clientSecret).getBytes()); - - ProxyResponse tokenResultResponse = getTokenResult(encodedClientApp, scopes); - - if (tokenResultResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { - log.error("Error occurred while invoking the API to get token data."); - HandlerUtil.handleError(req, resp, serverUrl, platform, tokenResultResponse); - return false; - } - String tokenResult = tokenResultResponse.getData(); - if (tokenResult == null){ - log.error("Invalid token response is received."); - HandlerUtil.handleError(req, resp, serverUrl, platform, tokenResultResponse); - return false; - } - - JsonElement jTokenResult = jsonParser.parse(tokenResult); - if (jTokenResult.isJsonObject()) { - JsonObject jTokenResultAsJsonObject = jTokenResult.getAsJsonObject(); - HttpSession session = req.getSession(false); - if (session == null) { - return false; - } - AuthData authData = new AuthData(); - authData.setClientId(clientId); - authData.setClientSecret(clientSecret); - authData.setEncodedClientApp(encodedClientApp); - authData.setAccessToken(jTokenResultAsJsonObject.get("access_token").getAsString()); - authData.setRefreshToken(jTokenResultAsJsonObject.get("refresh_token").getAsString()); - authData.setScope(jTokenResultAsJsonObject.get("scope").getAsString()); - session.setAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY, authData); - return true; - - } - } - return false; - } catch (IOException e) { - throw new LoginException("Error occured while sending the response into the socket", e); - } - } - - /*** - * - * @param scopes - scope Json Array and it is retrieved by reading UI config. - * @return string value of the defined scopes - */ - private String getScopeString(JsonArray scopes) { - if (scopes != null && scopes.size() > 0) { - StringBuilder builder = new StringBuilder(); - for (JsonElement scope : scopes) { - String tmpscope = scope.getAsString() + " "; - builder.append(tmpscope); - } - return builder.toString(); - } else { - return null; - } - } - - /*** - * - * @param req - {@link HttpServletRequest} - * Define username and password static parameters. - */ - private static void validateLoginRequest(HttpServletRequest req, HttpServletResponse resp) throws LoginException { - username = req.getParameter("username"); - password = req.getParameter("password"); - platform = req.getParameter("platform"); - serverUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort(); - uiConfigUrl = serverUrl + HandlerConstants.UI_CONFIG_ENDPOINT; - - try { - if (platform == null) { - resp.sendRedirect(serverUrl + HandlerConstants.DEFAULT_ERROR_CALLBACK); - throw new LoginException("Invalid login request. Platform parameter is Null."); - } - if (username == null || password == null) { - resp.sendRedirect(serverUrl + "/" + platform + HandlerConstants.DEFAULT_ERROR_CALLBACK); - throw new LoginException( - " Invalid login request. Username or Password is not received for login request."); - } - } catch (IOException e) { - throw new LoginException("Error Occured while redirecting to default error page.", e); - } - } - - /*** - * - * @param tags - tags which are retrieved by reading app manager configuration - * @return {@link StringEntity} of the payload to create the client application - */ - private StringEntity constructAppRegPayload(JsonArray tags) { - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty(HandlerConstants.APP_NAME_KEY, HandlerConstants.PUBLISHER_APPLICATION_NAME); - jsonObject.addProperty("isAllowedToAllDomains", "false"); - jsonObject.add(HandlerConstants.TAGS_KEY, tags); - String payload = jsonObject.toString(); - return new StringEntity(payload, ContentType.APPLICATION_JSON); - } - - /*** - * - * @param encodedClientApp - Base64 encoded clientId:clientSecret. - * @param scopes - Scopes which are retrieved by reading application-mgt configuration - * @return Invoke token endpoint and return the response as string. - * @throws IOException IO exception throws if an error occured when invoking token endpoint - */ - private ProxyResponse getTokenResult(String encodedClientApp, JsonArray scopes) throws IOException { - - HttpPost tokenEndpoint = new HttpPost(serverUrl + HandlerConstants.TOKEN_ENDPOINT); - tokenEndpoint.setHeader("Authorization", "Basic " + encodedClientApp); - tokenEndpoint.setHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.toString()); - String scopeString = getScopeString(scopes); - - if (scopeString != null) { - scopeString = scopeString.trim(); - } else { - scopeString = "default"; - } - - StringEntity tokenEPPayload = new StringEntity( - "grant_type=password&username=" + username + "&password=" + password + "&scope=" + scopeString, - ContentType.APPLICATION_FORM_URLENCODED); - tokenEndpoint.setEntity(tokenEPPayload); - return execute(tokenEndpoint); - } -} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/beans/AuthData.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/beans/AuthData.java deleted file mode 100644 index 20cd45a222..0000000000 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/beans/AuthData.java +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. - * - * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.device.application.mgt.handler.beans; - - -public class AuthData implements java.io.Serializable { - - private static final long serialVersionUID = -5156750882531944849L; - - private String accessToken; - private String refreshToken; - private String username; - private String clientId; - private String clientSecret; - private String encodedClientApp; - private String scope; - - public String getAccessToken() { - return accessToken; - } - - public void setAccessToken(String accessToken) { - this.accessToken = accessToken; - } - - public String getRefreshToken() { - return refreshToken; - } - - public void setRefreshToken(String refreshToken) { - this.refreshToken = refreshToken; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public String getClientSecret() { - return clientSecret; - } - - public void setClientSecret(String clientSecret) { - this.clientSecret = clientSecret; - } - - public String getEncodedClientApp() { - return encodedClientApp; - } - - public void setEncodedClientApp(String encodedClientApp) { - this.encodedClientApp = encodedClientApp; - } - - public String getScope() { - return scope; - } - - public void setScope(String scope) { - this.scope = scope; - } -} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/exceptions/LoginException.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/exceptions/LoginException.java deleted file mode 100644 index 1deda4add5..0000000000 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/exceptions/LoginException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2018, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. - * - * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.device.application.mgt.handler.exceptions; - -public class LoginException extends Exception { - public LoginException(String message) { - super(message); - } - - public LoginException(String message, Throwable cause) { - super(message, cause); - } - - public LoginException(Throwable cause) { - super(cause); - } - - public LoginException(String message, Throwable cause, - boolean enableSuppression, - boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/util/HandlerConstants.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/util/HandlerConstants.java deleted file mode 100644 index d8804ca834..0000000000 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/util/HandlerConstants.java +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (c) 2018, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. - * - * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.device.application.mgt.handler.util; - -public class HandlerConstants { - public static final String PUBLISHER_APPLICATION_NAME = "application-mgt-publisher"; - public static final String APP_REG_ENDPOINT = "/api-application-registration/register"; - public static final String UI_CONFIG_ENDPOINT = "/api/application-mgt/v1.0/config/ui-config"; - public static final String TOKEN_ENDPOINT = "/oauth2/token"; - public static final String AUTHORIZATION = "Authorization"; - public static final String BASIC = "Basic "; - public static final String COLON = ":"; - public static final String TAGS_KEY = "tags"; - public static final String APP_NAME_KEY = "applicationName"; - public static final String SESSION_AUTH_DATA_KEY = "application-mgt"; - public static final String AUTHORIZATION_HEADER_KEY = "Authorization"; - public static final String UI_CONFIG_KEY = "ui-config"; - public static final String PLATFORM = "platform"; - public static final String SERVER_HOST = "server-host"; - public static final String DEFAULT_ERROR_CALLBACK = "/pages/error/default"; - public static final String LOGIN_RESPONSE_KEY = "loginResponse"; - public static final String FAILURE_CALLBACK_KEY = "failureCallback"; - public static final String API_COMMON_CONTEXT = "/api"; - public static final String EXECUTOR_EXCEPTION_PREFIX = "ExecutorException-"; - public static final String TOKEN_IS_EXPIRED = "ACCESS_TOKEN_IS_EXPIRED"; - - public static final int INTERNAL_ERROR_CODE = 500; - public static final long TIMEOUT = 1200; -} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/util/HandlerUtil.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/util/HandlerUtil.java deleted file mode 100644 index e49659c980..0000000000 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/java/org/wso2/carbon/device/application/mgt/handler/util/HandlerUtil.java +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. - * - * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.device.application.mgt.handler.util; - -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.json.JSONException; -import org.json.JSONObject; -import org.wso2.carbon.device.application.mgt.common.ProxyResponse; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; - -public class HandlerUtil { - - private static final Log log = LogFactory.getLog(HandlerUtil.class); - - /*** - * - * @param httpMethod - httpMethod e.g:- HttpPost, HttpGet - * @param - HttpPost or HttpGet class - * @return response as string - * @throws IOException IO exception returns if error occurs when executing the httpMethod - */ - public static ProxyResponse execute(T httpMethod) throws IOException { - try (CloseableHttpClient client = HttpClients.createDefault()) { - HttpResponse response = null; - if (httpMethod instanceof HttpPost) { - HttpPost method = (HttpPost) httpMethod; - response = client.execute(method); - } else if (httpMethod instanceof HttpGet) { - HttpGet method = (HttpGet) httpMethod; - response = client.execute(method); - } else if (httpMethod instanceof HttpPut) { - HttpPut method = (HttpPut) httpMethod; - response = client.execute(method); - } else if (httpMethod instanceof HttpDelete) { - HttpDelete method = (HttpDelete) httpMethod; - response = client.execute(method); - } - - ProxyResponse proxyResponse = new ProxyResponse(); - if (response == null) { - proxyResponse.setCode(HandlerConstants.INTERNAL_ERROR_CODE); - proxyResponse.setExecutorResponse(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + getStatusKey( - HandlerConstants.INTERNAL_ERROR_CODE)); - return proxyResponse; - } else { - int statusCode = response.getStatusLine().getStatusCode(); - try (BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) { - StringBuilder result = new StringBuilder(); - String line; - while ((line = rd.readLine()) != null) { - result.append(line); - } - - String jsonString = result.toString(); - if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_CREATED) { - proxyResponse.setCode(statusCode); - proxyResponse.setData(jsonString); - proxyResponse.setExecutorResponse("SUCCESS"); - return proxyResponse; - } else if (statusCode == HttpStatus.SC_UNAUTHORIZED) { - if (jsonString.contains("Access token expired") || jsonString - .contains("Invalid input. Access token validation failed")) { - proxyResponse.setCode(statusCode); - proxyResponse.setExecutorResponse("ACCESS_TOKEN_IS_EXPIRED"); - return proxyResponse; - } else { - proxyResponse.setCode(statusCode); - proxyResponse.setData(jsonString); - proxyResponse.setExecutorResponse( - HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + getStatusKey(statusCode)); - return proxyResponse; - } - } - proxyResponse.setCode(statusCode); - proxyResponse.setData(jsonString); - proxyResponse - .setExecutorResponse(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + getStatusKey(statusCode)); - return proxyResponse; - } - } - } - } - - /*** - * - * @param statusCode Provide status code, e.g:- 400, 401, 500 etc - * @return relative status code key for given status code. - */ - public static String getStatusKey (int statusCode){ - String statusCodeKey; - - switch (statusCode) { - case HttpStatus.SC_INTERNAL_SERVER_ERROR: - statusCodeKey = "internalServerError"; - break; - case HttpStatus.SC_BAD_REQUEST: - statusCodeKey = "badRequest"; - break; - case HttpStatus.SC_UNAUTHORIZED: - statusCodeKey = "unauthorized"; - break; - case HttpStatus.SC_FORBIDDEN: - statusCodeKey = "forbidden"; - break; - case HttpStatus.SC_NOT_FOUND: - statusCodeKey = "notFound"; - break; - case HttpStatus.SC_METHOD_NOT_ALLOWED: - statusCodeKey = "methodNotAllowed"; - break; - case HttpStatus.SC_NOT_ACCEPTABLE: - statusCodeKey = "notAcceptable"; - break; - case HttpStatus.SC_UNSUPPORTED_MEDIA_TYPE: - statusCodeKey = "unsupportedMediaType"; - break; - default: - statusCodeKey = "defaultPage"; - break; - } - return statusCodeKey; - } - - - /*** - * - * @param resp {@link HttpServletResponse} - * Return Error Response. - */ - public static void handleError(HttpServletRequest req, HttpServletResponse resp, String serverUrl, - String platform, ProxyResponse proxyResponse) throws IOException { - - HttpSession httpSession = req.getSession(true); - Gson gson = new Gson(); - if (proxyResponse == null){ - proxyResponse = new ProxyResponse(); - proxyResponse.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR); - proxyResponse.setExecutorResponse(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil - .getStatusKey(HandlerConstants.INTERNAL_ERROR_CODE)); - } - if (platform == null){ - platform = "default"; - } - - resp.setStatus(proxyResponse.getCode()); - resp.setContentType("application/json"); - resp.setCharacterEncoding("UTF-8"); - - if (httpSession != null) { - JsonObject uiConfig = (JsonObject) httpSession.getAttribute(HandlerConstants.UI_CONFIG_KEY); - if (uiConfig == null){ - proxyResponse.setUrl(serverUrl + "/" + platform + HandlerConstants.DEFAULT_ERROR_CALLBACK); - } else{ - proxyResponse.setUrl(serverUrl + uiConfig.get(HandlerConstants.LOGIN_RESPONSE_KEY).getAsJsonObject() - .get(HandlerConstants.FAILURE_CALLBACK_KEY).getAsJsonObject() - .get(proxyResponse.getExecutorResponse().split(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)[1]) - .getAsString()); - } - } else { - proxyResponse.setUrl(serverUrl + "/" + platform + HandlerConstants.DEFAULT_ERROR_CALLBACK); - } - - proxyResponse.setExecutorResponse(null); - try (PrintWriter writer = resp.getWriter()) { - writer.write(gson.toJson(proxyResponse)); - } - } - - /*** - * - * @param resp {@link HttpServletResponse} - * Return Success Response. - */ - public static void handleSuccess(HttpServletRequest req, HttpServletResponse resp, String serverUrl, - String platform, ProxyResponse proxyResponse) throws IOException { - if (proxyResponse == null){ - handleError(req,resp,serverUrl,platform,proxyResponse); - return; - } - - resp.setStatus(proxyResponse.getCode()); - resp.setContentType("application/json"); - resp.setCharacterEncoding("UTF-8"); - - JSONObject response = new JSONObject(); - String redirectUrl = proxyResponse.getUrl(); - String responseData = proxyResponse.getData(); - - if (!StringUtils.isEmpty(redirectUrl)){ - response.put("url", redirectUrl); - } - if (!StringUtils.isEmpty(responseData)){ - try { - JSONObject responseDataJsonObj = new JSONObject(responseData); - response.put("data", responseDataJsonObj); - } catch (JSONException e) { - log.debug("Response data is not valid json string"); - response.put("data", responseData); - } - } - - try (PrintWriter writer = resp.getWriter()) { - writer.write(response.toString()); - } - } - -} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/webapp/META-INF/webapp-classloading.xml b/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/webapp/META-INF/webapp-classloading.xml deleted file mode 100644 index cc5b3c66d7..0000000000 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/webapp/META-INF/webapp-classloading.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - false - - - Carbon - diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/webapp/WEB-INF/web.xml b/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 76d16ffb08..0000000000 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.handler/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - Application Management Auth Webapp - - 60 - - - doAuthentication - false - - - - - managed-api-enabled - false - - - managed-api-owner - admin - - - isSharedWithAllTenants - true - - - - CorsFilter - org.apache.catalina.filters.CorsFilter - - cors.allowed.origins - * - - - cors.allowed.methods - GET,POST,DELETE,PUT - - - cors.allowed.headers - Content-Type - - - - - HttpHeaderSecurityFilter - org.apache.catalina.filters.HttpHeaderSecurityFilter - - hstsEnabled - false - - - - - ContentTypeBasedCachePreventionFilter - org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter - - patterns - text/html" ,application/json" ,text/plain - - - filterAction - enforce - - - httpHeaders - Cache-Control: no-store, no-cache, must-revalidate, private - - - - - HttpHeaderSecurityFilter - /* - - - - ContentTypeBasedCachePreventionFilter - /* - - - - CorsFilter - /* - - - \ No newline at end of file diff --git a/components/application-mgt/pom.xml b/components/application-mgt/pom.xml index 2e4899beb4..dd201be3c4 100644 --- a/components/application-mgt/pom.xml +++ b/components/application-mgt/pom.xml @@ -42,7 +42,6 @@ org.wso2.carbon.device.application.mgt.store.api org.wso2.carbon.device.application.mgt.publisher.ui org.wso2.carbon.device.application.mgt.store.ui - org.wso2.carbon.device.application.mgt.handler org.wso2.carbon.device.application.mgt.api From f15fdae8a56e1f71fef09f05d031436dc7a7b0b3 Mon Sep 17 00:00:00 2001 From: Madawa Soysa Date: Fri, 21 Jun 2019 17:16:26 +1000 Subject: [PATCH 5/5] Refactor ui request interceptor Related to: entgra/product-iots#103 --- .../request/interceptor/InvokerHandler.java | 16 +++++----- .../ui/request/interceptor/LoginHandler.java | 30 +++++++++---------- .../request/interceptor/util/HandlerUtil.java | 14 +++++---- 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java index 864f5d6801..8acf32b2f6 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/InvokerHandler.java @@ -58,8 +58,6 @@ import java.io.IOException; import java.util.Enumeration; import java.util.List; -import static io.entgra.ui.request.interceptor.util.HandlerUtil.execute; - @MultipartConfig @WebServlet( name = "RequestHandlerServlet", @@ -84,7 +82,7 @@ public class InvokerHandler extends HttpServlet { HttpPost postRequest = new HttpPost(generateBackendRequestURL(req)); generateRequestEntity(req, postRequest); postRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); - ProxyResponse proxyResponse = execute(postRequest); + ProxyResponse proxyResponse = HandlerUtil.execute(postRequest); if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) { proxyResponse = retryRequestWithRefreshedToken(req, resp, postRequest); @@ -113,7 +111,7 @@ public class InvokerHandler extends HttpServlet { HttpGet getRequest = new HttpGet(generateBackendRequestURL(req)); copyRequestHeaders(req, getRequest, false); getRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); - ProxyResponse proxyResponse = execute(getRequest); + ProxyResponse proxyResponse = HandlerUtil.execute(getRequest); if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) { proxyResponse = retryRequestWithRefreshedToken(req, resp, getRequest); if (proxyResponse == null) { @@ -139,7 +137,7 @@ public class InvokerHandler extends HttpServlet { HttpPut putRequest = new HttpPut(generateBackendRequestURL(req)); generateRequestEntity(req, putRequest); putRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); - ProxyResponse proxyResponse = execute(putRequest); + ProxyResponse proxyResponse = HandlerUtil.execute(putRequest); if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) { proxyResponse = retryRequestWithRefreshedToken(req, resp, putRequest); @@ -168,7 +166,7 @@ public class InvokerHandler extends HttpServlet { HttpDelete deleteRequest = new HttpDelete(generateBackendRequestURL(req)); copyRequestHeaders(req, deleteRequest, false); deleteRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); - ProxyResponse proxyResponse = execute(deleteRequest); + ProxyResponse proxyResponse = HandlerUtil.execute(deleteRequest); if (HandlerConstants.TOKEN_IS_EXPIRED.equals(proxyResponse.getExecutorResponse())) { proxyResponse = retryRequestWithRefreshedToken(req, resp, deleteRequest); if (proxyResponse == null) { @@ -202,7 +200,7 @@ public class InvokerHandler extends HttpServlet { List fileItemList = servletFileUpload.parseRequest(req); MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); - for (FileItem item : fileItemList) { + for (FileItem item: fileItemList) { if (!item.isFormField()) { entityBuilder.addPart(item.getFieldName(), new InputStreamBody(item.getInputStream(), ContentType.create(item.getContentType()), item.getName())); @@ -321,7 +319,7 @@ public class InvokerHandler extends HttpServlet { HttpRequestBase httpRequest) throws IOException { if (refreshToken(req, resp)) { httpRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BEARER + authData.getAccessToken()); - ProxyResponse proxyResponse = execute(httpRequest); + ProxyResponse proxyResponse = HandlerUtil.execute(httpRequest); if (proxyResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { log.error("Error occurred while invoking the API after refreshing the token."); HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse); @@ -363,7 +361,7 @@ public class InvokerHandler extends HttpServlet { encodedClientApp); tokenEndpoint.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.toString()); - ProxyResponse tokenResultResponse = execute(tokenEndpoint); + ProxyResponse tokenResultResponse = HandlerUtil.execute(tokenEndpoint); if (tokenResultResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { log.error("Error occurred while refreshing access token."); HandlerUtil.handleError(req, resp, serverUrl, platform, tokenResultResponse); diff --git a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java index 25516268c6..f35f0151e1 100644 --- a/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java +++ b/components/ui-request-interceptor/io.entgra.ui.request.interceptor/src/main/java/io/entgra/ui/request/interceptor/LoginHandler.java @@ -50,8 +50,6 @@ import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.Base64; -import static io.entgra.ui.request.interceptor.util.HandlerUtil.execute; - @MultipartConfig @WebServlet("/login") public class LoginHandler extends HttpServlet { @@ -78,12 +76,12 @@ public class LoginHandler extends HttpServlet { httpSession.invalidate(); } httpSession = req.getSession(true); - //setting session to expiry in 5 mins + //setting session to expiry in 5 minutes httpSession.setMaxInactiveInterval(Math.toIntExact(HandlerConstants.TIMEOUT)); HttpGet uiConfigEndpoint = new HttpGet(uiConfigUrl); JsonParser jsonParser = new JsonParser(); - ProxyResponse uiConfigResponse = execute(uiConfigEndpoint); + ProxyResponse uiConfigResponse = HandlerUtil.execute(uiConfigEndpoint); String executorResponse = uiConfigResponse.getExecutorResponse(); if (!StringUtils.isEmpty(executorResponse) && executorResponse .contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) { @@ -126,7 +124,7 @@ public class LoginHandler extends HttpServlet { apiRegEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()); apiRegEndpoint.setEntity(constructAppRegPayload(tags)); - ProxyResponse clientAppResponse = execute(apiRegEndpoint); + ProxyResponse clientAppResponse = HandlerUtil.execute(apiRegEndpoint); String clientAppResult = clientAppResponse.getData(); if (!StringUtils.isEmpty(clientAppResult) && getTokenAndPersistInSession(req, resp, @@ -141,11 +139,11 @@ public class LoginHandler extends HttpServlet { HandlerUtil.handleError(req, resp, serverUrl, platform, null); } } catch (IOException e) { - log.error("Error occured while sending the response into the socket. ", e); + log.error("Error occurred while sending the response into the socket. ", e); } catch (JsonSyntaxException e) { - log.error("Error occured while parsing the response. ", e); + log.error("Error occurred while parsing the response. ", e); } catch (LoginException e) { - log.error("Error occured while getting token data. ", e); + log.error("Error occurred while getting token data. ", e); } } @@ -203,7 +201,7 @@ public class LoginHandler extends HttpServlet { } return false; } catch (IOException e) { - throw new LoginException("Error occured while sending the response into the socket", e); + throw new LoginException("Error occurred while sending the response into the socket", e); } } @@ -216,8 +214,8 @@ public class LoginHandler extends HttpServlet { if (scopes != null && scopes.size() > 0) { StringBuilder builder = new StringBuilder(); for (JsonElement scope : scopes) { - String tmpscope = scope.getAsString() + " "; - builder.append(tmpscope); + String tmpScope = scope.getAsString() + " "; + builder.append(tmpScope); } return builder.toString(); } else { @@ -248,7 +246,7 @@ public class LoginHandler extends HttpServlet { " Invalid login request. Username or Password is not received for login request."); } } catch (IOException e) { - throw new LoginException("Error Occured while redirecting to default error page.", e); + throw new LoginException("Error occurred while redirecting to default error page.", e); } } @@ -271,13 +269,13 @@ public class LoginHandler extends HttpServlet { * @param encodedClientApp - Base64 encoded clientId:clientSecret. * @param scopes - Scopes which are retrieved by reading application-mgt configuration * @return Invoke token endpoint and return the response as string. - * @throws IOException IO exception throws if an error occured when invoking token endpoint + * @throws IOException IO exception throws if an error occurred when invoking token endpoint */ private ProxyResponse getTokenResult(String encodedClientApp, JsonArray scopes) throws IOException { HttpPost tokenEndpoint = new HttpPost(serverUrl + HandlerConstants.TOKEN_ENDPOINT); - tokenEndpoint.setHeader("Authorization", "Basic " + encodedClientApp); - tokenEndpoint.setHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.toString()); + tokenEndpoint.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BASIC + encodedClientApp); + tokenEndpoint.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.toString()); String scopeString = getScopeString(scopes); if (scopeString != null) { @@ -290,6 +288,6 @@ public class LoginHandler extends HttpServlet { "grant_type=password&username=" + username + "&password=" + password + "&scope=" + scopeString, ContentType.APPLICATION_FORM_URLENCODED); tokenEndpoint.setEntity(tokenEPPayload); - return execute(tokenEndpoint); + return HandlerUtil.execute(tokenEndpoint); } } 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 f3baea315f..399655ae0a 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,9 +23,11 @@ import com.google.gson.JsonObject; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.http.Consts; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.ContentType; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.json.JSONException; @@ -79,7 +81,7 @@ public class HandlerUtil { if (jsonString.contains("Access token expired") || jsonString .contains("Invalid input. Access token validation failed")) { proxyResponse.setCode(statusCode); - proxyResponse.setExecutorResponse("ACCESS_TOKEN_IS_EXPIRED"); + proxyResponse.setExecutorResponse(HandlerConstants.TOKEN_IS_EXPIRED); return proxyResponse; } else { proxyResponse.setCode(statusCode); @@ -161,8 +163,8 @@ public class HandlerUtil { } resp.setStatus(proxyResponse.getCode()); - resp.setContentType("application/json"); - resp.setCharacterEncoding("UTF-8"); + resp.setContentType(ContentType.APPLICATION_JSON.getMimeType()); + resp.setCharacterEncoding(Consts.UTF_8.name()); if (httpSession != null) { JsonObject uiConfig = (JsonObject) httpSession.getAttribute(HandlerConstants.UI_CONFIG_KEY); @@ -192,13 +194,13 @@ public class HandlerUtil { public static void handleSuccess(HttpServletRequest req, HttpServletResponse resp, String serverUrl, String platform, ProxyResponse proxyResponse) throws IOException { if (proxyResponse == null){ - handleError(req,resp,serverUrl,platform,proxyResponse); + handleError(req, resp, serverUrl, platform, null); return; } resp.setStatus(proxyResponse.getCode()); - resp.setContentType("application/json"); - resp.setCharacterEncoding("UTF-8"); + resp.setContentType(ContentType.APPLICATION_JSON.getMimeType()); + resp.setCharacterEncoding(Consts.UTF_8.name()); JSONObject response = new JSONObject(); String redirectUrl = proxyResponse.getUrl();