Skip to content
This repository was archived by the owner on Jan 23, 2025. It is now read-only.

Commit d9ef48f

Browse files
authored
Fix jwt token updater (#328)
* fix jwt token updater usage * and refactor jwt token updater a bit
1 parent c37e6ff commit d9ef48f

File tree

6 files changed

+51
-41
lines changed

6 files changed

+51
-41
lines changed

conf/web/WEB-INF/applicationContext.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@
357357
<property name="contestFeeService" ref="contestFeeService"/>
358358
<property name="contestFeePercentageService" ref="contestFeePercentageService"/>
359359
<property name="userGroupsApiEndpoint" value="@userGroupsApiEndpoint@"/>
360+
<property name="jwtTokenUpdater" ref="jwtTokenUpdater" />
360361
</bean>
361362

362363
<bean id="projectAction" class="com.topcoder.direct.services.view.action.contest.launch.ProjectAction"
@@ -1611,7 +1612,7 @@
16111612
<property name="groupApiEndpoint" value="@groupMemberApiUrl@"/>
16121613
<property name="jwtTokenUpdater" ref="jwtTokenUpdater"/>
16131614
</bean>
1614-
<bean id="jwtTokenUpdater" class="com.topcoder.direct.services.view.util.JwtTokenUpdater">
1615+
<bean id="jwtTokenUpdater" class="com.topcoder.direct.services.view.util.JwtTokenUpdater" scope="prototype">
16151616
<property name="ssoLoginUrl" value="@ssoLoginUrl@"/>
16161617
<property name="authorizationURL" value="@authorizationUrl@"/>
16171618
</bean>

src/java/main/com/topcoder/direct/services/view/action/contest/launch/CommonAction.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.topcoder.direct.services.view.util.AuthorizationProvider;
2121
import com.topcoder.direct.services.view.util.DataProvider;
2222
import com.topcoder.direct.services.view.util.DirectUtils;
23+
import com.topcoder.direct.services.view.util.JwtTokenUpdater;
2324
import com.topcoder.direct.services.view.util.challenge.CostCalculationService;
2425
import com.topcoder.management.project.ProjectGroup;
2526
import com.topcoder.security.TCSubject;
@@ -128,6 +129,8 @@ public class CommonAction extends BaseContestFeeAction {
128129
*/
129130
private String userGroupsApiEndpoint;
130131

132+
private JwtTokenUpdater jwtTokenUpdater;
133+
131134
/**
132135
* <p>
133136
* Executes the action.
@@ -558,7 +561,7 @@ public void setCategoryId(long categoryId) {
558561
public String getGroups() {
559562
try {
560563
TCSubject tcSubject = DirectUtils.getTCSubjectFromSession();
561-
Set<ProjectGroup> projectGroups = DirectUtils.getGroups(tcSubject, userGroupsApiEndpoint);
564+
Set<ProjectGroup> projectGroups = DirectUtils.getGroups(tcSubject, jwtTokenUpdater, userGroupsApiEndpoint);
562565
setResult(projectGroups);
563566
} catch (Throwable e) {
564567
if (getModel() != null) {
@@ -575,4 +578,12 @@ public String getUserGroupsApiEndpoint() {
575578
public void setUserGroupsApiEndpoint(String userGroupsApiEndpoint) {
576579
this.userGroupsApiEndpoint = userGroupsApiEndpoint;
577580
}
581+
582+
public JwtTokenUpdater getJwtTokenUpdater() {
583+
return jwtTokenUpdater;
584+
}
585+
586+
public void setJwtTokenUpdater(JwtTokenUpdater jwtTokenUpdater) {
587+
this.jwtTokenUpdater = jwtTokenUpdater;
588+
}
578589
}

src/java/main/com/topcoder/direct/services/view/action/my/MyChallengesAction.java

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import com.topcoder.direct.services.view.dto.my.Challenge;
88
import com.topcoder.direct.services.view.dto.my.RestResult;
99
import com.topcoder.direct.services.view.exception.JwtAuthenticationException;
10-
import com.topcoder.direct.services.view.util.JwtTokenUpdater;
1110
import org.codehaus.jackson.JsonNode;
1211

1312
import java.text.DateFormat;

src/java/main/com/topcoder/direct/services/view/exception/JwtAuthenticationException.java

+4
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,8 @@ public class JwtAuthenticationException extends BaseException {
66
public JwtAuthenticationException(String message) {
77
super(message);
88
}
9+
10+
public JwtAuthenticationException(String message, Throwable cause) {
11+
super(message, cause);
12+
}
913
}

src/java/main/com/topcoder/direct/services/view/util/DirectUtils.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -3824,11 +3824,12 @@ public static List<ProjectGroup> getGroupIdAndName(List<ProjectGroup> projectGro
38243824
* Get group from group API.
38253825
*
38263826
* @param tcSubject tcSubject of user
3827+
* @param jwtTokenUpdater the jwt token updater
38273828
* @param endpoint endpoint url
38283829
* @return set of group
38293830
* @throws Exception
38303831
*/
3831-
public static Set<ProjectGroup> getGroupsFromApi(TCSubject tcSubject, String endpoint) throws Exception {
3832+
public static Set<ProjectGroup> getGroupsFromApi(TCSubject tcSubject, JwtTokenUpdater jwtTokenUpdater, String endpoint) throws Exception {
38323833
URIBuilder uri = new URIBuilder(endpoint);
38333834

38343835
if (!DirectUtils.isCockpitAdmin(tcSubject) && !DirectUtils.isTcStaff(tcSubject)) {
@@ -3840,7 +3841,7 @@ public static Set<ProjectGroup> getGroupsFromApi(TCSubject tcSubject, String end
38403841
HttpGet getRequest = new HttpGet(uri.build());
38413842
logger.info("Getting Group with thi uri: " + uri.build().toString());
38423843

3843-
String v3Token = new JwtTokenUpdater().check().getToken();
3844+
String v3Token = jwtTokenUpdater.check().getToken();
38443845

38453846
getRequest.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + v3Token);
38463847

@@ -3867,11 +3868,12 @@ public static Set<ProjectGroup> getGroupsFromApi(TCSubject tcSubject, String end
38673868
* Get groups. Get from cache first if none then get from api
38683869
*
38693870
* @param tcSubject tcSubject of user
3871+
* @param jwtTokenUpdater the jwt token updater
38703872
* @param endpoint endpoint url
38713873
* @return set of groupfor user
38723874
* @throws Exception
38733875
*/
3874-
public static Set<ProjectGroup> getGroups(TCSubject tcSubject, String endpoint) throws Exception {
3876+
public static Set<ProjectGroup> getGroups(TCSubject tcSubject, JwtTokenUpdater jwtTokenUpdater, String endpoint) throws Exception {
38753877
CacheClient cc = null;
38763878
Set<ProjectGroup> projectGroups = null;
38773879
SortedCacheAddress cacheAddress = new SortedCacheAddress(tcSubject.getUserId());
@@ -3882,7 +3884,7 @@ public static Set<ProjectGroup> getGroups(TCSubject tcSubject, String endpoint)
38823884
logger.info("Can't get group for user " + tcSubject.getUserId() + " from cache");
38833885
}
38843886
if (projectGroups == null) {
3885-
projectGroups = DirectUtils.getGroupsFromApi(tcSubject, endpoint);
3887+
projectGroups = DirectUtils.getGroupsFromApi(tcSubject, jwtTokenUpdater, endpoint);
38863888
try {
38873889
cc.set(cacheAddress, projectGroups, MaxAge.HOUR);
38883890
} catch (Exception e) {

src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java

+27-34
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
package com.topcoder.direct.services.view.util;
55

66
import com.topcoder.direct.services.configs.ServerConfiguration;
7-
import com.topcoder.direct.services.view.dto.my.SingleRestResult;
8-
import com.topcoder.direct.services.view.dto.my.Token;
97
import com.topcoder.direct.services.view.exception.JwtAuthenticationException;
108
import org.apache.commons.codec.binary.Base64;
119
import org.apache.http.HttpEntity;
@@ -16,6 +14,7 @@
1614
import org.apache.http.entity.StringEntity;
1715
import org.apache.http.impl.client.DefaultHttpClient;
1816
import org.apache.log4j.Logger;
17+
import org.apache.struts2.ServletActionContext;
1918
import org.codehaus.jackson.JsonNode;
2019
import org.codehaus.jackson.map.DeserializationConfig;
2120
import org.codehaus.jackson.map.ObjectMapper;
@@ -26,8 +25,6 @@
2625
import java.text.SimpleDateFormat;
2726
import java.util.Date;
2827

29-
import org.apache.struts2.ServletActionContext;
30-
3128
import static sun.security.krb5.internal.Krb5.getErrorMessage;
3229

3330
/**
@@ -93,11 +90,10 @@ public JwtTokenUpdater check() throws Exception {
9390
}
9491

9592

96-
private Token getRefreshTokenFromApi(String oldToken) throws Exception {
93+
private String getRefreshTokenFromApi(String oldToken) throws Exception {
9794
DefaultHttpClient httpClient = new DefaultHttpClient();
98-
SingleRestResult<Token> resultToken = null;
9995
try {
100-
URI authorizationUri = new URI(getAuthorizationURL());
96+
URI authorizationUri = new URI(this.authorizationURL);
10197
HttpPost httpPost = new HttpPost(authorizationUri);
10298
httpPost.addHeader(HttpHeaders.CONTENT_TYPE, "application/json");
10399

@@ -112,57 +108,54 @@ private Token getRefreshTokenFromApi(String oldToken) throws Exception {
112108
}
113109

114110
JsonNode result = objectMapper.readTree(entity.getContent());
115-
resultToken = objectMapper.readValue(result.get("result"),
116-
objectMapper.getTypeFactory().constructParametricType(SingleRestResult.class, Token.class));
111+
112+
return result.path("result").path("content").path("token").asText();
117113
} finally {
118114
httpClient.getConnectionManager().shutdown();
119115
}
120-
return resultToken.getContent();
121116
}
122117

123118
/**
124-
* Verify token.If token expired: refresh it
119+
* Verify token. If token expired: refresh it
125120
*
126-
* @param tokenV3
127-
* @param tokenV2
121+
* @param v3token the v3 jwt token
122+
* @param v2token the v2 jwt token
128123
* @return
129124
* @throws JwtAuthenticationException
130125
*/
131-
private String getValidJwtToken(String tokenV3, String tokenV2) throws JwtAuthenticationException {
132-
String[] tokenSplit = tokenV3.split("\\.");
133-
boolean valid = true;
134-
if (tokenSplit.length < 2) valid = false;
135-
136-
JsonNode jsonNode = null;
126+
private String getValidJwtToken(String v3token, String v2token) throws JwtAuthenticationException {
127+
String[] tokenSplit = v3token.split("\\.");
128+
boolean valid = tokenSplit.length >= 2;
137129

138130
try {
139131
if (valid) {
140-
StringBuffer payloadStr = new StringBuffer(tokenSplit[1]);
132+
StringBuilder payloadStr = new StringBuilder(tokenSplit[1]);
141133
while (payloadStr.length() % 4 != 0) payloadStr.append('=');
142134
String payload = new String(Base64.decodeBase64(payloadStr.toString().getBytes(StandardCharsets.UTF_8)));
143135

144-
jsonNode = objectMapper.readValue(payload.toString(), JsonNode.class);
136+
JsonNode jsonNode = objectMapper.readValue(payload, JsonNode.class);
145137

146138
long exp = jsonNode.get("exp").getLongValue();
147139
Date expDate = new Date(exp * 1000);
148140
logger.info("token expire at: " + expDate);
149-
if (expDate.before(new Date())) valid = false;
150-
}
151-
152-
if (!valid) {
153-
logger.info("refresh new token for : " + tokenV2);
154-
Token newToken = getRefreshTokenFromApi(tokenV2);
155-
if (newToken == null || newToken.getToken().isEmpty()) {
156-
throw new JwtAuthenticationException("Invalid refresh token");
141+
if (expDate.after(new Date())) {
142+
return v3token;
157143
}
144+
}
158145

159-
return newToken.getToken();
146+
logger.info("refresh v3 token for : " + v2token);
147+
String newToken = getRefreshTokenFromApi(v2token);
148+
if (newToken == null || newToken.isEmpty()) {
149+
throw new JwtAuthenticationException("Invalid refreshed token - " + newToken);
160150
}
151+
152+
return newToken;
153+
} catch (JwtAuthenticationException e) {
154+
throw e;
161155
} catch (Exception e) {
162156
throw new JwtAuthenticationException("Failed to refresh toke through api, Please go to sso login page : " +
163-
getSsoLoginUrl());
157+
this.ssoLoginUrl, e);
164158
}
165-
return tokenV3;
166159
}
167160

168161
/**
@@ -172,11 +165,11 @@ private String getValidJwtToken(String tokenV3, String tokenV2) throws JwtAuthen
172165
* @param v3 cookie v3
173166
* @throws Exception
174167
*/
175-
private void validateCookieV2V3(Cookie v2, Cookie v3) throws Exception{
168+
private void validateCookieV2V3(Cookie v2, Cookie v3) throws Exception {
176169
String validToken;
177170
String v3Token = null;
178171
if (v3 == null) {
179-
validToken = getRefreshTokenFromApi(v2.getValue()).getToken();
172+
validToken = getRefreshTokenFromApi(v2.getValue());
180173
} else {
181174
validToken = getValidJwtToken(v3.getValue(), v2.getValue());
182175
v3Token = v3.getValue();

0 commit comments

Comments
 (0)