From f5ef717006982c28db65b82cc8fdcd7a203b824e Mon Sep 17 00:00:00 2001 From: Guiqiang Zhang Date: Tue, 17 Oct 2017 09:50:15 +0800 Subject: [PATCH 1/6] fix jwt token updater --- .../services/view/util/JwtTokenUpdater.java | 57 ++++++++----------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java b/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java index 1039b061f..5d4ccd2be 100644 --- a/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java +++ b/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java @@ -4,8 +4,6 @@ package com.topcoder.direct.services.view.util; import com.topcoder.direct.services.configs.ServerConfiguration; -import com.topcoder.direct.services.view.dto.my.SingleRestResult; -import com.topcoder.direct.services.view.dto.my.Token; import com.topcoder.direct.services.view.exception.JwtAuthenticationException; import org.apache.commons.codec.binary.Base64; import org.apache.http.HttpEntity; @@ -16,6 +14,7 @@ import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.log4j.Logger; +import org.apache.struts2.ServletActionContext; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.ObjectMapper; @@ -26,8 +25,6 @@ import java.text.SimpleDateFormat; import java.util.Date; -import org.apache.struts2.ServletActionContext; - import static sun.security.krb5.internal.Krb5.getErrorMessage; /** @@ -93,9 +90,8 @@ public JwtTokenUpdater check() throws Exception { } - private Token getRefreshTokenFromApi(String oldToken) throws Exception { + private String getRefreshTokenFromApi(String oldToken) throws Exception { DefaultHttpClient httpClient = new DefaultHttpClient(); - SingleRestResult resultToken = null; try { URI authorizationUri = new URI(getAuthorizationURL()); HttpPost httpPost = new HttpPost(authorizationUri); @@ -112,57 +108,54 @@ private Token getRefreshTokenFromApi(String oldToken) throws Exception { } JsonNode result = objectMapper.readTree(entity.getContent()); - resultToken = objectMapper.readValue(result.get("result"), - objectMapper.getTypeFactory().constructParametricType(SingleRestResult.class, Token.class)); + + return result.path("result").path("content").path("token").asText(); } finally { httpClient.getConnectionManager().shutdown(); } - return resultToken.getContent(); } /** - * Verify token.If token expired: refresh it + * Verify token. If token expired: refresh it * - * @param tokenV3 - * @param tokenV2 + * @param v3token the v3 jwt token + * @param v2token the v2 jwt token * @return * @throws JwtAuthenticationException */ - private String getValidJwtToken(String tokenV3, String tokenV2) throws JwtAuthenticationException { - String[] tokenSplit = tokenV3.split("\\."); - boolean valid = true; - if (tokenSplit.length < 2) valid = false; - - JsonNode jsonNode = null; + private String getValidJwtToken(String v3token, String v2token) throws JwtAuthenticationException { + String[] tokenSplit = v3token.split("\\."); + boolean valid = tokenSplit.length >= 2; try { if (valid) { - StringBuffer payloadStr = new StringBuffer(tokenSplit[1]); + StringBuilder payloadStr = new StringBuilder(tokenSplit[1]); while (payloadStr.length() % 4 != 0) payloadStr.append('='); String payload = new String(Base64.decodeBase64(payloadStr.toString().getBytes(StandardCharsets.UTF_8))); - jsonNode = objectMapper.readValue(payload.toString(), JsonNode.class); + JsonNode jsonNode = objectMapper.readValue(payload, JsonNode.class); long exp = jsonNode.get("exp").getLongValue(); Date expDate = new Date(exp * 1000); logger.info("token expire at: " + expDate); - if (expDate.before(new Date())) valid = false; - } - - if (!valid) { - logger.info("refresh new token for : " + tokenV2); - Token newToken = getRefreshTokenFromApi(tokenV2); - if (newToken == null || newToken.getToken().isEmpty()) { - throw new JwtAuthenticationException("Invalid refresh token"); + if (expDate.after(new Date())) { + return v3token; } + } - return newToken.getToken(); + logger.info("refresh v3 token for : " + v2token); + String newToken = getRefreshTokenFromApi(v2token); + if (newToken == null || newToken.isEmpty()) { + throw new JwtAuthenticationException("Invalid refreshed token - " + newToken); } + + return newToken; + } catch (JwtAuthenticationException e) { + throw e; } catch (Exception e) { throw new JwtAuthenticationException("Failed to refresh toke through api, Please go to sso login page : " + getSsoLoginUrl()); } - return tokenV3; } /** @@ -172,11 +165,11 @@ private String getValidJwtToken(String tokenV3, String tokenV2) throws JwtAuthen * @param v3 cookie v3 * @throws Exception */ - private void validateCookieV2V3(Cookie v2, Cookie v3) throws Exception{ + private void validateCookieV2V3(Cookie v2, Cookie v3) throws Exception { String validToken; String v3Token = null; if (v3 == null) { - validToken = getRefreshTokenFromApi(v2.getValue()).getToken(); + validToken = getRefreshTokenFromApi(v2.getValue()); } else { validToken = getValidJwtToken(v3.getValue(), v2.getValue()); v3Token = v3.getValue(); From ea6dc4884047ee0011ec3ea5d61e463840d07c81 Mon Sep 17 00:00:00 2001 From: Guiqiang Zhang Date: Tue, 17 Oct 2017 10:08:09 +0800 Subject: [PATCH 2/6] trace the inner exception --- .../services/view/exception/JwtAuthenticationException.java | 4 ++++ .../topcoder/direct/services/view/util/JwtTokenUpdater.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/java/main/com/topcoder/direct/services/view/exception/JwtAuthenticationException.java b/src/java/main/com/topcoder/direct/services/view/exception/JwtAuthenticationException.java index b9b913bdf..4d06154af 100644 --- a/src/java/main/com/topcoder/direct/services/view/exception/JwtAuthenticationException.java +++ b/src/java/main/com/topcoder/direct/services/view/exception/JwtAuthenticationException.java @@ -6,4 +6,8 @@ public class JwtAuthenticationException extends BaseException { public JwtAuthenticationException(String message) { super(message); } + + public JwtAuthenticationException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java b/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java index 5d4ccd2be..672e629c6 100644 --- a/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java +++ b/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java @@ -154,7 +154,7 @@ private String getValidJwtToken(String v3token, String v2token) throws JwtAuthen throw e; } catch (Exception e) { throw new JwtAuthenticationException("Failed to refresh toke through api, Please go to sso login page : " + - getSsoLoginUrl()); + getSsoLoginUrl(), e); } } From ca4b753c5ef10f57ff8544a305b391313c9973a9 Mon Sep 17 00:00:00 2001 From: Guiqiang Zhang Date: Tue, 17 Oct 2017 10:28:15 +0800 Subject: [PATCH 3/6] directly use varibles --- .../topcoder/direct/services/view/util/JwtTokenUpdater.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java b/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java index 672e629c6..d4e226dd5 100644 --- a/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java +++ b/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java @@ -93,7 +93,7 @@ public JwtTokenUpdater check() throws Exception { private String getRefreshTokenFromApi(String oldToken) throws Exception { DefaultHttpClient httpClient = new DefaultHttpClient(); try { - URI authorizationUri = new URI(getAuthorizationURL()); + URI authorizationUri = new URI(this.authorizationURL); HttpPost httpPost = new HttpPost(authorizationUri); httpPost.addHeader(HttpHeaders.CONTENT_TYPE, "application/json"); @@ -154,7 +154,7 @@ private String getValidJwtToken(String v3token, String v2token) throws JwtAuthen throw e; } catch (Exception e) { throw new JwtAuthenticationException("Failed to refresh toke through api, Please go to sso login page : " + - getSsoLoginUrl(), e); + this.ssoLoginUrl, e); } } From 6de3a281b6d15eb385b1af8f42ff8fac38e1dd80 Mon Sep 17 00:00:00 2001 From: Guiqiang Zhang Date: Tue, 17 Oct 2017 10:35:31 +0800 Subject: [PATCH 4/6] use prototype scope --- conf/web/WEB-INF/applicationContext.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/web/WEB-INF/applicationContext.xml b/conf/web/WEB-INF/applicationContext.xml index 431f8f5dd..678879f88 100644 --- a/conf/web/WEB-INF/applicationContext.xml +++ b/conf/web/WEB-INF/applicationContext.xml @@ -1611,7 +1611,7 @@ - + From 495b741052620ccb01aa5ff67750e6330149c7b9 Mon Sep 17 00:00:00 2001 From: Guiqiang Zhang Date: Tue, 17 Oct 2017 11:15:29 +0800 Subject: [PATCH 5/6] fix jwt token updater usage --- conf/web/WEB-INF/applicationContext.xml | 1 + .../view/action/contest/launch/CommonAction.java | 13 ++++++++++++- .../services/view/action/my/MyChallengesAction.java | 1 - .../direct/services/view/util/DirectUtils.java | 10 ++++++---- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/conf/web/WEB-INF/applicationContext.xml b/conf/web/WEB-INF/applicationContext.xml index 678879f88..e986b33a9 100644 --- a/conf/web/WEB-INF/applicationContext.xml +++ b/conf/web/WEB-INF/applicationContext.xml @@ -357,6 +357,7 @@ + * Executes the action. @@ -558,7 +561,7 @@ public void setCategoryId(long categoryId) { public String getGroups() { try { TCSubject tcSubject = DirectUtils.getTCSubjectFromSession(); - Set projectGroups = DirectUtils.getGroups(tcSubject, userGroupsApiEndpoint); + Set projectGroups = DirectUtils.getGroups(tcSubject, jwtTokenUpdater, userGroupsApiEndpoint); setResult(projectGroups); } catch (Throwable e) { if (getModel() != null) { @@ -575,4 +578,12 @@ public String getUserGroupsApiEndpoint() { public void setUserGroupsApiEndpoint(String userGroupsApiEndpoint) { this.userGroupsApiEndpoint = userGroupsApiEndpoint; } + + public JwtTokenUpdater getJwtTokenUpdater() { + return jwtTokenUpdater; + } + + public setJwtTokenUpdater(JwtTokenUpdater jwtTokenUpdater) { + this.jwtTokenUpdater = jwtTokenUpdater; + } } diff --git a/src/java/main/com/topcoder/direct/services/view/action/my/MyChallengesAction.java b/src/java/main/com/topcoder/direct/services/view/action/my/MyChallengesAction.java index 6f39dfa29..acf13817f 100644 --- a/src/java/main/com/topcoder/direct/services/view/action/my/MyChallengesAction.java +++ b/src/java/main/com/topcoder/direct/services/view/action/my/MyChallengesAction.java @@ -7,7 +7,6 @@ import com.topcoder.direct.services.view.dto.my.Challenge; import com.topcoder.direct.services.view.dto.my.RestResult; import com.topcoder.direct.services.view.exception.JwtAuthenticationException; -import com.topcoder.direct.services.view.util.JwtTokenUpdater; import org.codehaus.jackson.JsonNode; import java.text.DateFormat; diff --git a/src/java/main/com/topcoder/direct/services/view/util/DirectUtils.java b/src/java/main/com/topcoder/direct/services/view/util/DirectUtils.java index 118ef2057..ff833a80d 100644 --- a/src/java/main/com/topcoder/direct/services/view/util/DirectUtils.java +++ b/src/java/main/com/topcoder/direct/services/view/util/DirectUtils.java @@ -3824,11 +3824,12 @@ public static List getGroupIdAndName(List projectGro * Get group from group API. * * @param tcSubject tcSubject of user + * @param jwtTokenUpdater the jwt token updater * @param endpoint endpoint url * @return set of group * @throws Exception */ - public static Set getGroupsFromApi(TCSubject tcSubject, String endpoint) throws Exception { + public static Set getGroupsFromApi(TCSubject tcSubject, JwtTokenUpdater jwtTokenUpdater, String endpoint) throws Exception { URIBuilder uri = new URIBuilder(endpoint); if (!DirectUtils.isCockpitAdmin(tcSubject) && !DirectUtils.isTcStaff(tcSubject)) { @@ -3840,7 +3841,7 @@ public static Set getGroupsFromApi(TCSubject tcSubject, String end HttpGet getRequest = new HttpGet(uri.build()); logger.info("Getting Group with thi uri: " + uri.build().toString()); - String v3Token = new JwtTokenUpdater().check().getToken(); + String v3Token = jwtTokenUpdater.check().getToken(); getRequest.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + v3Token); @@ -3867,11 +3868,12 @@ public static Set getGroupsFromApi(TCSubject tcSubject, String end * Get groups. Get from cache first if none then get from api * * @param tcSubject tcSubject of user + * @param jwtTokenUpdater the jwt token updater * @param endpoint endpoint url * @return set of groupfor user * @throws Exception */ - public static Set getGroups(TCSubject tcSubject, String endpoint) throws Exception { + public static Set getGroups(TCSubject tcSubject, JwtTokenUpdater jwtTokenUpdater, String endpoint) throws Exception { CacheClient cc = null; Set projectGroups = null; SortedCacheAddress cacheAddress = new SortedCacheAddress(tcSubject.getUserId()); @@ -3882,7 +3884,7 @@ public static Set getGroups(TCSubject tcSubject, String endpoint) logger.info("Can't get group for user " + tcSubject.getUserId() + " from cache"); } if (projectGroups == null) { - projectGroups = DirectUtils.getGroupsFromApi(tcSubject, endpoint); + projectGroups = DirectUtils.getGroupsFromApi(tcSubject, jwtTokenUpdater, endpoint); try { cc.set(cacheAddress, projectGroups, MaxAge.HOUR); } catch (Exception e) { From d9a1de0e571be63ab4785e47ffbe406f31618219 Mon Sep 17 00:00:00 2001 From: Guiqiang Zhang Date: Tue, 17 Oct 2017 11:20:08 +0800 Subject: [PATCH 6/6] fix method definition --- .../services/view/action/contest/launch/CommonAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/main/com/topcoder/direct/services/view/action/contest/launch/CommonAction.java b/src/java/main/com/topcoder/direct/services/view/action/contest/launch/CommonAction.java index 4f6b02ec5..bd03ada39 100644 --- a/src/java/main/com/topcoder/direct/services/view/action/contest/launch/CommonAction.java +++ b/src/java/main/com/topcoder/direct/services/view/action/contest/launch/CommonAction.java @@ -583,7 +583,7 @@ public JwtTokenUpdater getJwtTokenUpdater() { return jwtTokenUpdater; } - public setJwtTokenUpdater(JwtTokenUpdater jwtTokenUpdater) { + public void setJwtTokenUpdater(JwtTokenUpdater jwtTokenUpdater) { this.jwtTokenUpdater = jwtTokenUpdater; } }