Fix app manager access token creating issue

feature/appm-store/pbac
lasanthaDLPDS 6 years ago
parent 42a4196ed4
commit 6fe5b11db1

@ -0,0 +1,42 @@
package org.wso2.carbon.device.application.mgt.common;
/* 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.
*/
public class ProxyResponse {
private int code;
private String url;
private String data;
private String executorResponse;
public int getCode() { return code; }
public void setCode(int code) { this.code = code; }
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getData() { return data; }
public void setData(String data) { this.data = data; }
public String getExecutorResponse() { return executorResponse; }
public void setExecutorResponse(String executorResponse) { this.executorResponse = executorResponse; }
}

@ -23,7 +23,6 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
@ -32,9 +31,10 @@ import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity; 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.beans.AuthData;
import org.wso2.carbon.device.application.mgt.handler.util.HandlerConstants; 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.MultipartConfig;
import javax.servlet.annotation.WebServlet; import javax.servlet.annotation.WebServlet;
@ -43,16 +43,12 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter;
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
import static org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil.execute; import static org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil.execute;
import static org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil.retrieveResponseString;
@MultipartConfig @MultipartConfig @WebServlet("/invoke")
@WebServlet("/invoke")
public class InvokerHandler extends HttpServlet { public class InvokerHandler extends HttpServlet {
private static final Log log = LogFactory.getLog(LoginHandler.class); private static final Log log = LogFactory.getLog(LoginHandler.class);
private static final long serialVersionUID = -6508020875358160165L; private static final long serialVersionUID = -6508020875358160165L;
@ -60,174 +56,171 @@ public class InvokerHandler extends HttpServlet {
private static String apiEndpoint; private static String apiEndpoint;
private static String method; private static String method;
private static String serverUrl; 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 {
HttpSession session = req.getSession(false);
if (session == null) {
resp.sendError(HTTP_UNAUTHORIZED, "Unauthorized, You are not logged in. Please log in to the portal");
return false;
}
authData = (AuthData) session.getAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY);
platform = (String) session.getAttribute(HandlerConstants.PLATFORM);
if (authData == null) {
resp.sendError(HTTP_UNAUTHORIZED, "Unauthorized, Access token couldn't found in the current session");
return false;
}
apiEndpoint = req.getParameter("api-endpoint");
method = req.getParameter("method");
serverUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort();
if (apiEndpoint == null || method == null) {
resp.sendError(HTTP_BAD_REQUEST, "Bad Request, Either api-endpoint or method is empty");
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;
}
// @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) { log.error("Error Occurred in token renewal process.");
// try { ProxyResponse proxyResponse = new ProxyResponse();
// if (!validateRequest(req, resp)) { proxyResponse.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
// return; proxyResponse.setExecutorResponse(
// } HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil.getStatusKey(HttpStatus.SC_INTERNAL_SERVER_ERROR));
// HandlerUtil.handleError(req, resp, serverUrl, platform, proxyResponse);
// HttpRequestBase executor = constructExecutor(req); return false;
// if (executor == null) { }
// resp.sendError(HTTP_BAD_REQUEST, "Bad Request, method: " + method + " is not supported");
// return;
// }
// String accessToken = authData.getAccessToken();
// executor.setHeader("Authorization", "Bearer " + accessToken);
//
// String result = execute(executor, HttpStatus.SC_OK);
//
//// unauthorized
//// if (response == null) {
//// resp.sendError(HTTP_INTERNAL_ERROR, "Empty response retried for the API call.");
//// return;
//// }
//
//// int responseCode = response.getStatusLine().getStatusCode();
//// String result = retrieveResponseString(response);
//
// if (responseCode == HttpStatus.SC_UNAUTHORIZED && (result.contains("Access token expired") || result
// .contains("Invalid input. Access token validation failed"))) {
// if (!refreshToken(req, resp)) {
// return;
// }
// response = execute(executor);
// if (response == null) {
// resp.sendError(HTTP_INTERNAL_ERROR, "Empty response retried for the token renewal API call.");
// return;
// }
// responseCode = response.getStatusLine().getStatusCode();
// result = retrieveResponseString(response);
// }
// if (responseCode != HttpStatus.SC_OK && responseCode != HttpStatus.SC_CREATED) {
// resp.sendError(responseCode, "Error response retrieved for the API call.");
// return;
// }
// try (PrintWriter writer = resp.getWriter()) {
// writer.write(result);
// }
// } 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 {
// HttpSession session = req.getSession(false);
// if (session == null) {
// resp.sendError(HTTP_UNAUTHORIZED, "Unauthorized, You are not logged in. Please log in to the portal");
// return false;
// }
// authData = (AuthData) session.getAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY);
// if (authData == null) {
// resp.sendError(HTTP_UNAUTHORIZED, "Unauthorized, Access token couldn't found in the current session");
// return false;
// }
//
// apiEndpoint = req.getParameter("api-endpoint");
// method = req.getParameter("method");
//
// serverUrl = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort();
// if (apiEndpoint == null || method == null) {
// resp.sendError(HTTP_BAD_REQUEST, "Bad Request, Either api-endpoint or method is empty");
// 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) {
// resp.sendError(HTTP_UNAUTHORIZED, "Session is expired. Please log in to the server.");
// 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());
//
// HttpResponse response = execute(tokenEndpoint);
// if (response == null) {
// resp.sendError(HTTP_INTERNAL_ERROR,
// "Internal Server Error, response of the token refresh API call is null.");
// return false;
// } else if ((response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)) {
// resp.sendError(response.getStatusLine().getStatusCode(),
// "Error occured while getting new access token by using refresh token.");
// return false;
// }
// String tokenResult = retrieveResponseString(response);
// JsonParser jsonParser = new JsonParser();
//
// JsonElement jTokenResult = jsonParser.parse(tokenResult);
// 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;
// }
// return false;
// }
} }

@ -22,16 +22,16 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HTTP;
import org.wso2.carbon.device.application.mgt.common.config.UIConfiguration; 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.beans.AuthData;
import org.wso2.carbon.device.application.mgt.handler.exceptions.LoginException; 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.HandlerConstants;
@ -50,8 +50,7 @@ import java.util.Base64;
import static org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil.execute; import static org.wso2.carbon.device.application.mgt.handler.util.HandlerUtil.execute;
@MultipartConfig @MultipartConfig @WebServlet("/login")
@WebServlet("/login")
public class LoginHandler extends HttpServlet { public class LoginHandler extends HttpServlet {
private static final Log log = LogFactory.getLog(LoginHandler.class); private static final Log log = LogFactory.getLog(LoginHandler.class);
private static final long serialVersionUID = 9050048549140517002L; private static final long serialVersionUID = 9050048549140517002L;
@ -61,10 +60,8 @@ public class LoginHandler extends HttpServlet {
private static String platform; private static String platform;
private static String serverUrl; private static String serverUrl;
private static String uiConfigUrl; private static String uiConfigUrl;
private static JsonObject uiConfig;
@Override @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
try { try {
validateLoginRequest(req, resp); validateLoginRequest(req, resp);
DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance() DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance()
@ -82,25 +79,38 @@ public class LoginHandler extends HttpServlet {
HttpGet uiConfigEndpoint = new HttpGet(uiConfigUrl); HttpGet uiConfigEndpoint = new HttpGet(uiConfigUrl);
JsonParser jsonParser = new JsonParser(); JsonParser jsonParser = new JsonParser();
String uiConfigJsonString = execute(uiConfigEndpoint,HttpStatus.SC_OK); ProxyResponse uiConfigResponse = execute(uiConfigEndpoint);
if (uiConfigJsonString.contains(HandlerConstants.EXECUTOR_XCEPTIO_PRFIX)){ 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); log.error("Error occurred while getting UI configurations by invoking " + uiConfigUrl);
handleErrorResponse(resp, uiConfigJsonString); HandlerUtil.handleError(req, resp, serverUrl, platform, uiConfigResponse);
return;
} }
JsonElement uiConfigJsonElement = jsonParser.parse(uiConfigJsonString); String uiConfig = uiConfigResponse.getData();
JsonObject uiConfigAsJsonObject = null ; 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()) { if (uiConfigJsonElement.isJsonObject()) {
uiConfigAsJsonObject = uiConfigJsonElement.getAsJsonObject(); uiConfigJsonObject = uiConfigJsonElement.getAsJsonObject();
httpSession.setAttribute(HandlerConstants.UI_CONFIG_KEY, uiConfigJsonObject);
httpSession.setAttribute(HandlerConstants.PLATFORM, serverUrl);
} }
if (uiConfigAsJsonObject == null) { if (uiConfigJsonObject == null) {
resp.sendRedirect(serverUrl + "/" + platform + HandlerConstants.DEFAULT_ERROR_CALLBACK); 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; return;
} }
boolean isSsoEnable = uiConfigAsJsonObject.get("isSsoEnable").getAsBoolean(); boolean isSsoEnable = uiConfigJsonObject.get("isSsoEnable").getAsBoolean();
JsonArray tags = uiConfigAsJsonObject.get("appRegistration").getAsJsonObject().get("tags").getAsJsonArray(); JsonArray tags = uiConfigJsonObject.get("appRegistration").getAsJsonObject().get("tags").getAsJsonArray();
JsonArray scopes = uiConfigAsJsonObject.get("scopes").getAsJsonArray(); JsonArray scopes = uiConfigJsonObject.get("scopes").getAsJsonArray();
if (isSsoEnable) { if (isSsoEnable) {
log.debug("SSO is enabled"); log.debug("SSO is enabled");
@ -112,18 +122,19 @@ public class LoginHandler extends HttpServlet {
apiRegEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()); apiRegEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
apiRegEndpoint.setEntity(constructAppRegPayload(tags)); apiRegEndpoint.setEntity(constructAppRegPayload(tags));
String clientAppResult = execute(apiRegEndpoint, HttpStatus.SC_CREATED); ProxyResponse clientAppResponse = execute(apiRegEndpoint);
String clientAppResult = clientAppResponse.getData();
if (!clientAppResult.isEmpty() && persistTokenInSession(req, resp, clientAppResult, scopes)) { if (!StringUtils.isEmpty(clientAppResult) && getTokenAndPersistInSession(req, resp,
resp.sendRedirect( clientAppResponse.getData(), scopes)) {
serverUrl + "/" + platform + uiConfigAsJsonObject.get(HandlerConstants.LOGIN_RESPONSE_KEY) ProxyResponse proxyResponse = new ProxyResponse();
.getAsJsonObject().get("successCallback").getAsString()); 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; return;
} }
resp.sendRedirect( HandlerUtil.handleError(req, resp, serverUrl, platform, null);
serverUrl + "/" + platform + uiConfigAsJsonObject.get(HandlerConstants.LOGIN_RESPONSE_KEY)
.getAsJsonObject().get(HandlerConstants.FAILURE_CALLBACK_KEY).getAsJsonObject()
.get(HandlerUtil.getStatusKey(HandlerConstants.INTERNAL_ERROR_CODE)).getAsString());
} }
} catch (IOException e) { } catch (IOException e) {
log.error("Error occured while sending the response into the socket. ", e); log.error("Error occured while sending the response into the socket. ", e);
@ -141,11 +152,9 @@ public class LoginHandler extends HttpServlet {
* @param scopes - scopes defied in the application-mgt.xml * @param scopes - scopes defied in the application-mgt.xml
* @throws LoginException - login exception throws when getting token result * @throws LoginException - login exception throws when getting token result
*/ */
private boolean persistTokenInSession(HttpServletRequest req, HttpServletResponse resp, String clientAppResult, private boolean getTokenAndPersistInSession(HttpServletRequest req, HttpServletResponse resp,
JsonArray scopes) throws LoginException { String clientAppResult, JsonArray scopes) throws LoginException {
JsonParser jsonParser = new JsonParser(); JsonParser jsonParser = new JsonParser();
String tokenResult;
try { try {
JsonElement jClientAppResult = jsonParser.parse(clientAppResult); JsonElement jClientAppResult = jsonParser.parse(clientAppResult);
if (jClientAppResult.isJsonObject()) { if (jClientAppResult.isJsonObject()) {
@ -155,26 +164,37 @@ public class LoginHandler extends HttpServlet {
String encodedClientApp = Base64.getEncoder() String encodedClientApp = Base64.getEncoder()
.encodeToString((clientId + ":" + clientSecret).getBytes()); .encodeToString((clientId + ":" + clientSecret).getBytes());
tokenResult = getTokenResult(encodedClientApp, scopes, resp); ProxyResponse tokenResultResponse = getTokenResult(encodedClientApp, scopes);
if (tokenResult != null) { if (tokenResultResponse.getExecutorResponse().contains(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX)) {
JsonElement jTokenResult = jsonParser.parse(tokenResult); log.error("Error occurred while invoking the API to get token data.");
if (jTokenResult.isJsonObject()) { HandlerUtil.handleError(req, resp, serverUrl, platform, tokenResultResponse);
JsonObject jTokenResultAsJsonObject = jTokenResult.getAsJsonObject(); return false;
HttpSession session = req.getSession(false); }
if (session == null) { String tokenResult = tokenResultResponse.getData();
return false; if (tokenResult == null){
} log.error("Invalid token response is received.");
AuthData authData = new AuthData(); HandlerUtil.handleError(req, resp, serverUrl, platform, tokenResultResponse);
authData.setClientId(clientId); return false;
authData.setClientSecret(clientSecret); }
authData.setEncodedClientApp(encodedClientApp);
authData.setAccessToken(jTokenResultAsJsonObject.get("access_token").getAsString()); JsonElement jTokenResult = jsonParser.parse(tokenResult);
authData.setRefreshToken(jTokenResultAsJsonObject.get("refresh_token").getAsString()); if (jTokenResult.isJsonObject()) {
authData.setScope(jTokenResultAsJsonObject.get("scope").getAsString()); JsonObject jTokenResultAsJsonObject = jTokenResult.getAsJsonObject();
session.setAttribute(HandlerConstants.SESSION_AUTH_DATA_KEY, authData); HttpSession session = req.getSession(false);
return true; 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; return false;
@ -246,50 +266,27 @@ public class LoginHandler extends HttpServlet {
* *
* @param encodedClientApp - Base64 encoded clientId:clientSecret. * @param encodedClientApp - Base64 encoded clientId:clientSecret.
* @param scopes - Scopes which are retrieved by reading application-mgt configuration * @param scopes - Scopes which are retrieved by reading application-mgt configuration
* @param resp - {@link HttpServletResponse}
* @return Invoke token endpoint and return the response as string. * @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 occured when invoking token endpoint
*/ */
private String getTokenResult(String encodedClientApp, JsonArray scopes, HttpServletResponse resp) private ProxyResponse getTokenResult(String encodedClientApp, JsonArray scopes) throws IOException {
throws IOException, LoginException {
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();
}
StringEntity tokenEPPayload = new StringEntity( HttpPost tokenEndpoint = new HttpPost(serverUrl + HandlerConstants.TOKEN_ENDPOINT);
"grant_type=password&username=" + username + "&password=" + password + "&scope=" + scopeString, tokenEndpoint.setHeader("Authorization", "Basic " + encodedClientApp);
ContentType.APPLICATION_FORM_URLENCODED); tokenEndpoint.setHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.toString());
tokenEndpoint.setEntity(tokenEPPayload); String scopeString = getScopeString(scopes);
String tokenResult = execute(tokenEndpoint, HttpStatus.SC_OK); if (scopeString != null) {
scopeString = scopeString.trim();
} else {
scopeString = "default";
}
if (tokenResult.contains(HandlerConstants.EXECUTOR_XCEPTIO_PRFIX)) { StringEntity tokenEPPayload = new StringEntity(
log.error("Error occurred while getting token data by invoking " + serverUrl "grant_type=password&username=" + username + "&password=" + password + "&scope=" + scopeString,
+ HandlerConstants.TOKEN_ENDPOINT); ContentType.APPLICATION_FORM_URLENCODED);
handleErrorResponse(resp, tokenResult); tokenEndpoint.setEntity(tokenEPPayload);
}
return tokenResult;
}
/*** return execute(tokenEndpoint);
*
* @param resp {@link HttpServletResponse}
* corresponding error page.
* @throws LoginException If an {@link IOException} occurs when redirecting to corresponding error page.
*/
private void handleErrorResponse(HttpServletResponse resp, String respMessage) throws LoginException {
try {
resp.sendRedirect(serverUrl + uiConfig.get(HandlerConstants.LOGIN_RESPONSE_KEY).getAsJsonObject()
.get(HandlerConstants.FAILURE_CALLBACK_KEY).getAsJsonObject()
.get(respMessage.split(HandlerConstants.EXECUTOR_XCEPTIO_PRFIX)[0]).getAsString());
} catch (IOException e) {
throw new LoginException("Error occured while redirecting to corresponding error page. ", e);
}
} }
} }

@ -28,11 +28,16 @@ public class HandlerConstants {
public static final String TAGS_KEY = "tags"; public static final String TAGS_KEY = "tags";
public static final String APP_NAME_KEY = "applicationName"; public static final String APP_NAME_KEY = "applicationName";
public static final String SESSION_AUTH_DATA_KEY = "application-mgt"; 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 DEFAULT_ERROR_CALLBACK = "/pages/error/default";
public static final String LOGIN_RESPONSE_KEY = "loginResponse"; public static final String LOGIN_RESPONSE_KEY = "loginResponse";
public static final String FAILURE_CALLBACK_KEY = "FailureCallback"; public static final String FAILURE_CALLBACK_KEY = "failureCallback";
public static final String API_COMMON_CONTEXT = "/api"; public static final String API_COMMON_CONTEXT = "/api";
public static final String EXECUTOR_XCEPTIO_PRFIX = "ExecutorException-"; 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 int INTERNAL_ERROR_CODE = 500;
public static final long TIMEOUT = 300; public static final long TIMEOUT = 300;

@ -17,9 +17,8 @@
package org.wso2.carbon.device.application.mgt.handler.util; package org.wso2.carbon.device.application.mgt.handler.util;
import com.google.gson.JsonElement; import com.google.gson.Gson;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
@ -28,16 +27,19 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;
import org.wso2.carbon.device.application.mgt.handler.exceptions.LoginException; 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.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.PrintWriter;
public class HandlerUtil { public class HandlerUtil {
private static final Log log = LogFactory.getLog(HandlerUtil.class); private static final Log log = LogFactory.getLog(HandlerUtil.class);
private static JsonObject uiConfigAsJsonObject;
/*** /***
* *
@ -46,9 +48,9 @@ public class HandlerUtil {
* @return response as string * @return response as string
* @throws IOException IO exception returns if error occurs when executing the httpMethod * @throws IOException IO exception returns if error occurs when executing the httpMethod
*/ */
public static <T> String execute(T httpMethod, int expectedStatusCode) throws IOException { public static <T> ProxyResponse execute(T httpMethod) throws IOException {
HttpResponse response = null;
try (CloseableHttpClient client = HttpClients.createDefault()) { try (CloseableHttpClient client = HttpClients.createDefault()) {
HttpResponse response = null;
if (httpMethod instanceof HttpPost) { if (httpMethod instanceof HttpPost) {
HttpPost method = (HttpPost) httpMethod; HttpPost method = (HttpPost) httpMethod;
response = client.execute(method); response = client.execute(method);
@ -57,46 +59,50 @@ public class HandlerUtil {
response = client.execute(method); response = client.execute(method);
} }
ProxyResponse proxyResponse = new ProxyResponse();
if (response == null) { if (response == null) {
return HandlerConstants.EXECUTOR_XCEPTIO_PRFIX + getStatusKey(HandlerConstants.INTERNAL_ERROR_CODE); proxyResponse.setCode(HandlerConstants.INTERNAL_ERROR_CODE);
proxyResponse.setExecutorResponse(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + getStatusKey(
HandlerConstants.INTERNAL_ERROR_CODE));
return proxyResponse;
} else { } else {
int statusCode = response.getStatusLine().getStatusCode(); int statusCode = response.getStatusLine().getStatusCode();
if ( statusCode != expectedStatusCode) { try (BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) {
return HandlerConstants.EXECUTOR_XCEPTIO_PRFIX + getStatusKey(statusCode); StringBuilder result = new StringBuilder();
} else { String line;
try (BufferedReader rd = new BufferedReader( while ((line = rd.readLine()) != null) {
new InputStreamReader(response.getEntity().getContent()))) { result.append(line);
StringBuilder result = new StringBuilder(); }
String line;
while ((line = rd.readLine()) != null) { String jsonString = result.toString();
result.append(line); 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;
} }
return result.toString();
} }
proxyResponse.setCode(statusCode);
proxyResponse
.setExecutorResponse(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + getStatusKey(statusCode));
return proxyResponse;
} }
} }
} }
} }
/***
*
* @param response {@link HttpResponse}
* @return {@link String} get the response payload by using Entity of the response
* @throws IOException if error occurs while reading the content of the response or reading {@link BufferedReader}
* object
*/
public static String retrieveResponseString (HttpResponse response) throws IOException{
try (BufferedReader rd = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()))) {
StringBuilder result = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
return result.toString();
}
}
/*** /***
* *
* @param statusCode Provide status code, e.g:- 400, 401, 500 etc * @param statusCode Provide status code, e.g:- 400, 401, 500 etc
@ -106,28 +112,28 @@ public class HandlerUtil {
String statusCodeKey; String statusCodeKey;
switch (statusCode) { switch (statusCode) {
case 500: case HttpStatus.SC_INTERNAL_SERVER_ERROR:
statusCodeKey = "internalServerError"; statusCodeKey = "internalServerError";
break; break;
case 400: case HttpStatus.SC_BAD_REQUEST:
statusCodeKey = "badRequest"; statusCodeKey = "badRequest";
break; break;
case 401: case HttpStatus.SC_UNAUTHORIZED:
statusCodeKey = "unauthorized"; statusCodeKey = "unauthorized";
break; break;
case 403: case HttpStatus.SC_FORBIDDEN:
statusCodeKey = "forbidden"; statusCodeKey = "forbidden";
break; break;
case 404: case HttpStatus.SC_NOT_FOUND:
statusCodeKey = "notFound"; statusCodeKey = "notFound";
break; break;
case 405: case HttpStatus.SC_METHOD_NOT_ALLOWED:
statusCodeKey = "methodNotAllowed"; statusCodeKey = "methodNotAllowed";
break; break;
case 406: case HttpStatus.SC_NOT_ACCEPTABLE:
statusCodeKey = "notAcceptable"; statusCodeKey = "notAcceptable";
break; break;
case 415: case HttpStatus.SC_UNSUPPORTED_MEDIA_TYPE:
statusCodeKey = "unsupportedMediaType"; statusCodeKey = "unsupportedMediaType";
break; break;
default: default:
@ -137,33 +143,68 @@ public class HandlerUtil {
return statusCodeKey; return statusCodeKey;
} }
/*** /***
* *
* @param uiConfigUrl - JSON string of the UI configuration * @param resp {@link HttpServletResponse}
* @return - True returns if UI config load is succeeded and False returns if it fails. Further, if call ie * Return Error Response.
* succeeded assign values for uiConfigAsJsonObject static variable.
* @throws LoginException IO exception could occur if an error occured when invoking end point for getting UI
* configs
*/ */
public static JsonObject loadUiConfig(String uiConfigUrl) throws LoginException { public static void handleError(HttpServletRequest req, HttpServletResponse resp, String serverUrl,
try { String platform, ProxyResponse proxyResponse) throws IOException {
if (uiConfigAsJsonObject != null) {
return uiConfigAsJsonObject; HttpSession httpSession = req.getSession(true);
} Gson gson = new Gson();
HttpGet uiConfigEndpoint = new HttpGet(uiConfigUrl); if (proxyResponse == null){
JsonParser jsonParser = new JsonParser(); proxyResponse = new ProxyResponse();
String uiConfig = execute(uiConfigEndpoint,HttpStatus.SC_OK); proxyResponse.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
proxyResponse.setExecutorResponse(HandlerConstants.EXECUTOR_EXCEPTION_PREFIX + HandlerUtil
JsonElement uiConfigJsonElement = jsonParser.parse(uiConfig); .getStatusKey(HandlerConstants.INTERNAL_ERROR_CODE));
if (uiConfigJsonElement.isJsonObject()) { }
uiConfigAsJsonObject = uiConfigJsonElement.getAsJsonObject();
return uiConfigAsJsonObject; 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;
}
} catch (IOException e) { Gson gson = new Gson();
throw new LoginException("Error occured while getting UI configs. ", e); resp.setStatus(proxyResponse.getCode());
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
proxyResponse.setExecutorResponse(null);
try (PrintWriter writer = resp.getWriter()) {
writer.write(gson.toJson(proxyResponse));
} }
return null;
} }
} }

Loading…
Cancel
Save