diff --git a/src/java/main/com/topcoder/direct/services/configs/ServerConfiguration.java b/src/java/main/com/topcoder/direct/services/configs/ServerConfiguration.java
index 7029d99bd..b57312455 100644
--- a/src/java/main/com/topcoder/direct/services/configs/ServerConfiguration.java
+++ b/src/java/main/com/topcoder/direct/services/configs/ServerConfiguration.java
@@ -55,7 +55,5 @@ public class ServerConfiguration extends ApplicationServer {
*
* @since 1.1
*/
- public static String JWT_COOOKIE_KEY = bundle.getProperty("JWT_COOKIE_KEY", "tcjwt");
-
- public static String JWT_V3_COOKIE_KEY = bundle.getProperty("JWT_V3_COOKIE_KEY", "v3jwt");
+ public static String JWT_COOKIE_KEY = bundle.getProperty("JWT_COOKIE_KEY", "tcjwt");
}
diff --git a/src/java/main/com/topcoder/direct/services/view/action/ServiceBackendDataTablesAction.java b/src/java/main/com/topcoder/direct/services/view/action/ServiceBackendDataTablesAction.java
index 4806d94c5..362e21de9 100644
--- a/src/java/main/com/topcoder/direct/services/view/action/ServiceBackendDataTablesAction.java
+++ b/src/java/main/com/topcoder/direct/services/view/action/ServiceBackendDataTablesAction.java
@@ -3,11 +3,11 @@
*/
package com.topcoder.direct.services.view.action;
+import com.topcoder.direct.services.configs.ServerConfiguration;
import com.topcoder.direct.services.view.dto.contest.ContestStatus;
import com.topcoder.direct.services.view.dto.project.ProjectBriefDTO;
import com.topcoder.direct.services.view.util.DataProvider;
import com.topcoder.direct.services.view.util.DirectUtils;
-import com.topcoder.direct.services.view.util.JwtTokenUpdater;
import com.topcoder.security.TCSubject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
@@ -17,6 +17,7 @@
import org.apache.http.client.utils.URIBuilder;
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;
@@ -215,11 +216,6 @@ public abstract class ServiceBackendDataTablesAction extends AbstractAction {
*/
protected static final ObjectMapper objectMapper;
- /**
- * JwtTokenUpdater
- */
- private JwtTokenUpdater jwtTokenUpdater;
-
/**
* A static Map mapping the existing contest statuses to their textual presentations.
*
@@ -323,7 +319,8 @@ protected JsonNode getJsonResultFromAPI(URI apiEndPoint) throws Exception {
// specify the get request
HttpGet getRequest = new HttpGet(apiEndPoint);
- String token = jwtTokenUpdater.getV3Token();
+ String token = DirectUtils.getCookieFromRequest(ServletActionContext.getRequest(),
+ ServerConfiguration.JWT_COOKIE_KEY).getValue();
getRequest.setHeader(HttpHeaders.AUTHORIZATION,
"Bearer " + token);
@@ -702,12 +699,4 @@ public String getEndDateTo() {
public void setEndDateTo(String endDateTo) {
this.endDateTo = endDateTo;
}
-
- public JwtTokenUpdater getJwtTokenUpdater() {
- return jwtTokenUpdater;
- }
-
- public void setJwtTokenUpdater(JwtTokenUpdater jwtTokenUpdater) {
- this.jwtTokenUpdater = jwtTokenUpdater;
- }
}
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 bd03ada39..c5c2360fc 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
@@ -20,7 +20,6 @@
import com.topcoder.direct.services.view.util.AuthorizationProvider;
import com.topcoder.direct.services.view.util.DataProvider;
import com.topcoder.direct.services.view.util.DirectUtils;
-import com.topcoder.direct.services.view.util.JwtTokenUpdater;
import com.topcoder.direct.services.view.util.challenge.CostCalculationService;
import com.topcoder.management.project.ProjectGroup;
import com.topcoder.security.TCSubject;
@@ -129,7 +128,6 @@ public class CommonAction extends BaseContestFeeAction {
*/
private String userGroupsApiEndpoint;
- private JwtTokenUpdater jwtTokenUpdater;
/**
*
@@ -561,7 +559,7 @@ public void setCategoryId(long categoryId) {
public String getGroups() {
try {
TCSubject tcSubject = DirectUtils.getTCSubjectFromSession();
- Set projectGroups = DirectUtils.getGroups(tcSubject, jwtTokenUpdater, userGroupsApiEndpoint);
+ Set projectGroups = DirectUtils.getGroups(tcSubject, userGroupsApiEndpoint);
setResult(projectGroups);
} catch (Throwable e) {
if (getModel() != null) {
@@ -578,12 +576,4 @@ public String getUserGroupsApiEndpoint() {
public void setUserGroupsApiEndpoint(String userGroupsApiEndpoint) {
this.userGroupsApiEndpoint = userGroupsApiEndpoint;
}
-
- public JwtTokenUpdater getJwtTokenUpdater() {
- return jwtTokenUpdater;
- }
-
- public void setJwtTokenUpdater(JwtTokenUpdater jwtTokenUpdater) {
- this.jwtTokenUpdater = jwtTokenUpdater;
- }
}
diff --git a/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetGroupMemberAction.java b/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetGroupMemberAction.java
index a62b0470c..57c02ecc3 100644
--- a/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetGroupMemberAction.java
+++ b/src/java/main/com/topcoder/direct/services/view/action/contest/launch/GetGroupMemberAction.java
@@ -6,9 +6,7 @@
import com.topcoder.direct.services.configs.ServerConfiguration;
import com.topcoder.direct.services.view.dto.contest.GroupMember;
import com.topcoder.direct.services.view.dto.my.RestResult;
-import com.topcoder.direct.services.view.exception.JwtAuthenticationException;
import com.topcoder.direct.services.view.util.DirectUtils;
-import com.topcoder.direct.services.view.util.JwtTokenUpdater;
import com.topcoder.direct.services.view.util.SortedCacheAddress;
import com.topcoder.web.common.cache.CacheClient;
import com.topcoder.web.common.cache.CacheClientFactory;
@@ -27,9 +25,13 @@
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
-import javax.servlet.http.Cookie;
import java.net.URI;
-import java.util.*;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
/**
* This action handle group member search for given list of groups and substringof user's handle
@@ -62,11 +64,6 @@ class GetGroupMemberAction extends ContestAction {
*/
private String handle;
- /**
- * JwtTokenUpdater
- */
- private JwtTokenUpdater jwtTokenUpdater;
-
/**
* Json object mapper
*/
@@ -188,13 +185,8 @@ private RestResult getGroupMemberByGid(Long gid) throws Exception {
try{
URI groupApiEndpointUri = new URI(String.format(groupApiEndpoint, gid));
HttpGet request = new HttpGet(groupApiEndpointUri);
- String jwtToken;
- try{
- jwtToken = jwtTokenUpdater.getV3Token();
- } catch (Exception e) {
- logger.error("Can't get jwt token");
- throw e;
- }
+ String jwtToken = DirectUtils.getCookieFromRequest(ServletActionContext.getRequest(),
+ ServerConfiguration.JWT_COOKIE_KEY).getValue();
request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + jwtToken);
request.addHeader(HttpHeaders.ACCEPT, "application/json");
@@ -239,12 +231,4 @@ public String getHandle() {
public void setHandle(String handle) {
this.handle = handle;
}
-
- public JwtTokenUpdater getJwtTokenUpdater() {
- return jwtTokenUpdater;
- }
-
- public void 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 a8f35544d..4585311c5 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
@@ -3,19 +3,20 @@
*/
package com.topcoder.direct.services.view.action.my;
-import com.topcoder.direct.services.configs.ServerConfiguration;
import com.topcoder.direct.services.view.action.ServiceBackendDataTablesAction;
import com.topcoder.direct.services.view.dto.my.Challenge;
import com.topcoder.direct.services.view.dto.my.RestResult;
-import com.topcoder.direct.services.view.util.DirectUtils;
import org.codehaus.jackson.JsonNode;
-import org.apache.struts2.ServletActionContext;
-
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
/**
*
@@ -49,10 +50,6 @@ public class MyChallengesAction extends ServiceBackendDataTablesAction {
*/
@Override
public String execute() throws Exception {
- if (DirectUtils.getCookieFromRequest(ServletActionContext.getRequest(),
- ServerConfiguration.JWT_COOOKIE_KEY) == null)
- return "forward";
-
// populate filter data
this.setupFilterPanel();
diff --git a/src/java/main/com/topcoder/direct/services/view/action/my/MyCreatedChallengesAction.java b/src/java/main/com/topcoder/direct/services/view/action/my/MyCreatedChallengesAction.java
index ecc0fea93..b0155acb9 100644
--- a/src/java/main/com/topcoder/direct/services/view/action/my/MyCreatedChallengesAction.java
+++ b/src/java/main/com/topcoder/direct/services/view/action/my/MyCreatedChallengesAction.java
@@ -2,14 +2,11 @@
* Copyright (C) 2014 TopCoder Inc., All Rights Reserved.
*/
package com.topcoder.direct.services.view.action.my;
-
-import com.topcoder.direct.services.configs.ServerConfiguration;
import com.topcoder.direct.services.view.action.ServiceBackendDataTablesAction;
import com.topcoder.direct.services.view.dto.my.Challenge;
import com.topcoder.direct.services.view.dto.my.RestResult;
import com.topcoder.direct.services.view.util.DirectUtils;
import com.topcoder.service.user.UserService;
-import org.apache.struts2.ServletActionContext;
import org.codehaus.jackson.JsonNode;
import java.text.DateFormat;
@@ -60,10 +57,6 @@ public class MyCreatedChallengesAction extends ServiceBackendDataTablesAction {
*/
@Override
public String execute() throws Exception {
- if (DirectUtils.getCookieFromRequest(ServletActionContext.getRequest(),
- ServerConfiguration.JWT_COOOKIE_KEY) == null)
- return "forward";
-
// populate filter data
this.setupFilterPanel();
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
deleted file mode 100644
index 4d06154af..000000000
--- a/src/java/main/com/topcoder/direct/services/view/exception/JwtAuthenticationException.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.topcoder.direct.services.view.exception;
-
-import com.topcoder.util.errorhandling.BaseException;
-
-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/interceptors/AuthenticationInterceptor.java b/src/java/main/com/topcoder/direct/services/view/interceptors/AuthenticationInterceptor.java
index 8851aafca..76ec4ef56 100644
--- a/src/java/main/com/topcoder/direct/services/view/interceptors/AuthenticationInterceptor.java
+++ b/src/java/main/com/topcoder/direct/services/view/interceptors/AuthenticationInterceptor.java
@@ -5,7 +5,6 @@
package com.topcoder.direct.services.view.interceptors;
-import java.util.Arrays;
import java.util.Set;
import javax.servlet.http.Cookie;
@@ -24,10 +23,8 @@
import com.topcoder.direct.services.view.util.SessionData;
import com.topcoder.direct.services.view.util.DirectUtils;
import com.topcoder.direct.services.view.util.DirectProperties;
-import com.topcoder.security.RolePrincipal;
import com.topcoder.security.TCPrincipal;
import com.topcoder.security.TCSubject;
-import com.topcoder.shared.security.SimpleResource;
import com.topcoder.shared.security.User;
import com.topcoder.shared.util.DBMS;
import com.topcoder.shared.util.logging.Logger;
@@ -224,6 +221,11 @@ public class AuthenticationInterceptor extends AbstractInterceptor {
*/
private String redirectBackUrlIdentityKey;
+ /**
+ * Endpoint from token updater
+ */
+ private String authorizationURL;
+
/**
* Default constructor, constructs an instance of this class.
*/
@@ -284,7 +286,7 @@ public String intercept(ActionInvocation invocation) throws Exception {
User user = auth.getActiveUser();
Cookie jwtCookie = DirectUtils.getCookieFromRequest(ServletActionContext.getRequest(),
- ServerConfiguration.JWT_COOOKIE_KEY);
+ ServerConfiguration.JWT_COOKIE_KEY);
if (jwtCookie == null) {
return loginPageName;
@@ -293,12 +295,17 @@ public String intercept(ActionInvocation invocation) throws Exception {
JWTToken jwtToken = null;
try {
jwtToken = new JWTToken(jwtCookie.getValue(),DirectProperties.CLIENT_SECRET_AUTH0,
- DirectProperties.JWT_VALID_ISSUERS, new JWTToken.Base64SecretEncoder());
+ DirectProperties.JWT_VALID_ISSUERS, authorizationURL, new JWTToken.Base64SecretEncoder());
+ jwtToken.verify();
} catch (TokenExpiredException e) {
- //refresh token here
- //redirect to loginpage for now
- logger.error("Token is expired. Should do refresh token here");
- return loginPageName;
+ logger.error("Token is expired. Try to refresh");
+ try {
+ jwtToken = jwtToken.refresh();
+ } catch (Exception ex) {
+ logger.error("Failed to refresh token: " + ex.getMessage());
+ logger.info("Redirect to login page");
+ return loginPageName;
+ }
} catch (Exception e) {
return loginPageName;
}
@@ -437,4 +444,12 @@ public void setRedirectBackUrlIdentityKey(String redirectBackUrlIdentityKey) {
Helper.checkNotNullOrEmpty(redirectBackUrlIdentityKey, "redirectBackUrlIdentityKey");
this.redirectBackUrlIdentityKey = redirectBackUrlIdentityKey;
}
+
+ public String getAuthorizationURL() {
+ return authorizationURL;
+ }
+
+ public void setAuthorizationURL(String authorizationURL) {
+ this.authorizationURL = authorizationURL;
+ }
}
diff --git a/src/java/main/com/topcoder/direct/services/view/processor/security/LoginProcessor.java b/src/java/main/com/topcoder/direct/services/view/processor/security/LoginProcessor.java
index a0953df7a..1d65ee27c 100644
--- a/src/java/main/com/topcoder/direct/services/view/processor/security/LoginProcessor.java
+++ b/src/java/main/com/topcoder/direct/services/view/processor/security/LoginProcessor.java
@@ -3,7 +3,6 @@
*/
package com.topcoder.direct.services.view.processor.security;
-import com.auth0.jwt.algorithms.Algorithm;
import com.topcoder.direct.services.configs.ServerConfiguration;
import com.topcoder.direct.services.view.action.LoginAction;
import com.topcoder.direct.services.view.form.LoginForm;
@@ -11,7 +10,6 @@
import com.topcoder.direct.services.view.util.DirectProperties;
import com.topcoder.direct.services.view.util.DirectUtils;
import com.topcoder.direct.services.view.util.jwt.DirectJWTSigner;
-import com.topcoder.direct.services.view.util.jwt.JWTToken;
import com.topcoder.security.TCSubject;
import com.topcoder.security.login.AuthenticationException;
import com.topcoder.security.login.LoginRemote;
@@ -133,7 +131,7 @@ public void processRequest(LoginAction action) {
// add session cookie, use -1 for expiration time
log.info("Signed JWT: " + sign);
DirectUtils.addDirectCookie(ServletActionContext.getResponse(),
- ServerConfiguration.JWT_COOOKIE_KEY, sign, -1);
+ ServerConfiguration.JWT_COOKIE_KEY, sign, -1);
} catch (AuthenticationException e) {
log.error("User " + username + " failed to authenticate successfully due to invalid credentials", e);
diff --git a/src/java/main/com/topcoder/direct/services/view/processor/security/MockLoginProcessor.java b/src/java/main/com/topcoder/direct/services/view/processor/security/MockLoginProcessor.java
index f06b45803..2cafbe783 100644
--- a/src/java/main/com/topcoder/direct/services/view/processor/security/MockLoginProcessor.java
+++ b/src/java/main/com/topcoder/direct/services/view/processor/security/MockLoginProcessor.java
@@ -3,7 +3,6 @@
*/
package com.topcoder.direct.services.view.processor.security;
-import com.auth0.jwt.algorithms.Algorithm;
import com.topcoder.direct.services.configs.ServerConfiguration;
import com.topcoder.direct.services.view.action.LoginAction;
import com.topcoder.direct.services.view.form.LoginForm;
@@ -11,7 +10,6 @@
import com.topcoder.direct.services.view.util.DirectProperties;
import com.topcoder.direct.services.view.util.DirectUtils;
import com.topcoder.direct.services.view.util.jwt.DirectJWTSigner;
-import com.topcoder.direct.services.view.util.jwt.JWTToken;
import com.topcoder.security.RolePrincipal;
import com.topcoder.security.TCPrincipal;
import com.topcoder.security.TCSubject;
@@ -213,7 +211,7 @@ public void processRequest(LoginAction action) {
log.info("SIgned JWT: " + sign);
// add session cookie, use -1 for expiration time
DirectUtils.addDirectCookie(ServletActionContext.getResponse(),
- ServerConfiguration.JWT_COOOKIE_KEY, sign, -1);
+ ServerConfiguration.JWT_COOKIE_KEY, sign, -1);
} catch (Exception e) {
log.error("User " + username + " could not set cookie", e);
log.error(e.getMessage() + e.getCause());
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 1b96f0952..5d578a3fd 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
@@ -18,7 +18,16 @@
import com.topcoder.direct.services.view.action.BaseDirectStrutsAction;
import com.topcoder.direct.services.view.action.specreview.ViewSpecificationReviewActionResultData;
import com.topcoder.direct.services.view.dto.IdNamePair;
-import com.topcoder.direct.services.view.dto.contest.*;
+import com.topcoder.direct.services.view.dto.contest.BaseContestCommonDTO;
+import com.topcoder.direct.services.view.dto.contest.ContestBriefDTO;
+import com.topcoder.direct.services.view.dto.contest.ContestDashboardDTO;
+import com.topcoder.direct.services.view.dto.contest.ContestRoundType;
+import com.topcoder.direct.services.view.dto.contest.ContestStatsDTO;
+import com.topcoder.direct.services.view.dto.contest.ContestStatus;
+import com.topcoder.direct.services.view.dto.contest.PhasedContestDTO;
+import com.topcoder.direct.services.view.dto.contest.ProjectPhaseDTO;
+import com.topcoder.direct.services.view.dto.contest.ProjectPhaseType;
+import com.topcoder.direct.services.view.dto.contest.TermOfUse;
import com.topcoder.direct.services.view.dto.cost.CostDTO;
import com.topcoder.direct.services.view.dto.project.ProjectBriefDTO;
import com.topcoder.direct.services.view.interceptor.SecurityGroupsAccessInterceptor;
@@ -26,7 +35,13 @@
import com.topcoder.management.deliverable.Submission;
import com.topcoder.management.deliverable.Upload;
import com.topcoder.management.deliverable.persistence.UploadPersistenceException;
-import com.topcoder.management.project.*;
+import com.topcoder.management.project.CopilotContestExtraInfo;
+import com.topcoder.management.project.CopilotContestExtraInfoType;
+import com.topcoder.management.project.Prize;
+import com.topcoder.management.project.ProjectCopilotType;
+import com.topcoder.management.project.ProjectGroup;
+import com.topcoder.management.project.ProjectPropertyType;
+import com.topcoder.management.project.ProjectType;
import com.topcoder.management.resource.Resource;
import com.topcoder.management.resource.ResourceRole;
import com.topcoder.management.review.data.Comment;
@@ -95,7 +110,13 @@
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
-import java.io.*;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.nio.channels.FileLock;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -103,7 +124,23 @@
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@@ -3770,12 +3807,11 @@ 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, JwtTokenUpdater jwtTokenUpdater, String endpoint) throws Exception {
+ public static Set getGroupsFromApi(TCSubject tcSubject, String endpoint) throws Exception {
URIBuilder uri = new URIBuilder(endpoint);
if (!DirectUtils.isCockpitAdmin(tcSubject) && !DirectUtils.isTcStaff(tcSubject)) {
@@ -3787,7 +3823,7 @@ public static Set getGroupsFromApi(TCSubject tcSubject, JwtTokenUp
HttpGet getRequest = new HttpGet(uri.build());
logger.info("Getting Group with thi uri: " + uri.build().toString());
- String v3Token = jwtTokenUpdater.getV3Token();
+ String v3Token = getCookieFromRequest(getServletRequest(), ServerConfiguration.JWT_COOKIE_KEY).getValue();
getRequest.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + v3Token);
@@ -3814,12 +3850,11 @@ public static Set getGroupsFromApi(TCSubject tcSubject, JwtTokenUp
* 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, JwtTokenUpdater jwtTokenUpdater, String endpoint) throws Exception {
+ public static Set getGroups(TCSubject tcSubject, String endpoint) throws Exception {
CacheClient cc = null;
Set projectGroups = null;
SortedCacheAddress cacheAddress = new SortedCacheAddress(tcSubject.getUserId());
@@ -3830,7 +3865,7 @@ public static Set getGroups(TCSubject tcSubject, JwtTokenUpdater j
logger.info("Can't get group for user " + tcSubject.getUserId() + " from cache");
}
if (projectGroups == null) {
- projectGroups = DirectUtils.getGroupsFromApi(tcSubject, jwtTokenUpdater, endpoint);
+ projectGroups = DirectUtils.getGroupsFromApi(tcSubject, endpoint);
try {
cc.set(cacheAddress, projectGroups, MaxAge.HOUR);
} catch (Exception e) {
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
deleted file mode 100644
index 7e6edd4cb..000000000
--- a/src/java/main/com/topcoder/direct/services/view/util/JwtTokenUpdater.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2017 TopCoder Inc., All Rights Reserved.
- */
-package com.topcoder.direct.services.view.util;
-
-import com.topcoder.direct.services.configs.ServerConfiguration;
-import com.topcoder.direct.services.view.exception.JwtAuthenticationException;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpHeaders;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.client.methods.HttpPost;
-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;
-
-import javax.servlet.http.Cookie;
-import java.net.URI;
-import java.nio.charset.StandardCharsets;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import static sun.security.krb5.internal.Krb5.getErrorMessage;
-
-/**
- * Utility class to check and update token from cookie
- *
- */
-public class JwtTokenUpdater {
-
- private static final Logger logger = Logger.getLogger(JwtTokenUpdater.class);
-
- /**
- * authorizationUrl
- */
- private String authorizationURL;
-
- /**
- * ssoLogin Url
- */
- private String ssoLoginUrl;
-
- protected static final String ERROR_MESSAGE_FORMAT = "Service URL:%s, HTTP Status Code:%d, Error Message:%s";
-
- private static final String AUTHORIZATION_PARAMS = "{\"param\": {\"externalToken\": \"%s\"}}";
-
- protected static final ObjectMapper objectMapper;
-
- static {
- objectMapper = new ObjectMapper();
- objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- objectMapper.setDateFormat(new SimpleDateFormat("MM/dd/yyyy HH:mm"));
- }
-
- public JwtTokenUpdater() {
-
- }
-
- /**
- * Validate and get v3 token from cookies
- *
- * @return v3 token
- * @throws Exception
- */
- public String getV3Token() throws Exception {
- Cookie jwtCookieV3 = DirectUtils.getCookieFromRequest(ServletActionContext.getRequest(),
- ServerConfiguration.JWT_V3_COOKIE_KEY);
- Cookie jwtCookieV2 = DirectUtils.getCookieFromRequest(ServletActionContext.getRequest(),
- ServerConfiguration.JWT_COOOKIE_KEY);
-
- if (jwtCookieV2 == null) {
- throw new JwtAuthenticationException("Please re-login");
- }
-
- return validateCookieV2V3(jwtCookieV2,jwtCookieV3);
- }
-
-
- private String getRefreshTokenFromApi(String oldToken) throws Exception {
- DefaultHttpClient httpClient = new DefaultHttpClient();
- try {
- URI authorizationUri = new URI(this.authorizationURL);
- HttpPost httpPost = new HttpPost(authorizationUri);
- httpPost.addHeader(HttpHeaders.CONTENT_TYPE, "application/json");
-
- StringEntity body = new StringEntity(String.format(AUTHORIZATION_PARAMS, oldToken));
- httpPost.setEntity(body);
- HttpResponse response = httpClient.execute(httpPost);
- HttpEntity entity = response.getEntity();
- if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
- throw new JwtAuthenticationException(String.format(ERROR_MESSAGE_FORMAT, authorizationUri,
- response.getStatusLine().getStatusCode(),
- getErrorMessage(response.getStatusLine().getStatusCode())));
- }
-
- JsonNode result = objectMapper.readTree(entity.getContent());
-
- return result.path("result").path("content").path("token").asText();
- } finally {
- httpClient.getConnectionManager().shutdown();
- }
- }
-
- /**
- * Verify token. If token expired: refresh it
- *
- * @param v3token the v3 jwt token
- * @param v2token the v2 jwt token
- * @return
- * @throws JwtAuthenticationException
- */
- private String getValidJwtToken(String v3token, String v2token) throws JwtAuthenticationException {
- String[] tokenSplit = v3token.split("\\.");
- boolean valid = tokenSplit.length >= 2;
-
- try {
- if (valid) {
- 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 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.after(new Date())) {
- return v3token;
- }
- }
-
- 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 : " +
- this.ssoLoginUrl, e);
- }
- }
-
- /**
- * Validate cookie v2 and v3
- *
- * @param v2 cookie v2
- * @param v3 cookie v3
- * @return valid v3 token
- * @throws Exception
- */
- private String validateCookieV2V3(Cookie v2, Cookie v3) throws Exception {
- String validToken;
- String v3Token = null;
- if (v3 == null) {
- validToken = getRefreshTokenFromApi(v2.getValue());
- } else {
- validToken = getValidJwtToken(v3.getValue(), v2.getValue());
- v3Token = v3.getValue();
- }
-
- if (!validToken.equals(v3Token)) {
- DirectUtils.addDirectCookie(ServletActionContext.getResponse(), ServerConfiguration.JWT_V3_COOKIE_KEY, validToken, -1);
- }
-
- return validToken;
- }
-
-
- public String getAuthorizationURL() {
- return authorizationURL;
- }
-
- public void setAuthorizationURL(String authorizationURL) {
- this.authorizationURL = authorizationURL;
- }
-
- public String getSsoLoginUrl() {
- return ssoLoginUrl;
- }
-
- public void setSsoLoginUrl(String ssoLoginUrl) {
- this.ssoLoginUrl = ssoLoginUrl;
- }
-}
diff --git a/src/java/main/com/topcoder/direct/services/view/util/jwt/JWTEndpointException.java b/src/java/main/com/topcoder/direct/services/view/util/jwt/JWTEndpointException.java
new file mode 100644
index 000000000..c50b346b1
--- /dev/null
+++ b/src/java/main/com/topcoder/direct/services/view/util/jwt/JWTEndpointException.java
@@ -0,0 +1,11 @@
+package com.topcoder.direct.services.view.util.jwt;
+
+public class JWTEndpointException extends JWTException {
+ public JWTEndpointException(String message) {
+ super(message);
+ }
+
+ public JWTEndpointException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/java/main/com/topcoder/direct/services/view/util/jwt/JWTToken.java b/src/java/main/com/topcoder/direct/services/view/util/jwt/JWTToken.java
index d97a647b6..99a964236 100644
--- a/src/java/main/com/topcoder/direct/services/view/util/jwt/JWTToken.java
+++ b/src/java/main/com/topcoder/direct/services/view/util/jwt/JWTToken.java
@@ -3,13 +3,25 @@
*/
package com.topcoder.direct.services.view.util.jwt;
+import java.net.URI;
import java.security.interfaces.RSAPublicKey;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import org.apache.commons.codec.binary.Base64;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHeaders;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.DeserializationConfig;
+import org.codehaus.jackson.map.ObjectMapper;
import com.auth0.jwk.GuavaCachedJwkProvider;
import com.auth0.jwk.Jwk;
@@ -24,6 +36,8 @@
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.Verification;
+import static sun.security.krb5.internal.Krb5.getErrorMessage;
+
/**
* Jwt token. Main purpose is to verify token.
* Verification based on token signature, issuers, and time validation
@@ -69,6 +83,25 @@ public class JWTToken {
protected SecretEncoder encoder = new Base64SecretEncoder();
+ private boolean valid = false;
+
+ /**
+ * authorizationUrl
+ */
+ private String authorizationURL;
+
+ protected static final String ERROR_MESSAGE_FORMAT = "Service URL:%s, HTTP Status Code:%d, Error Message:%s";
+
+ private static final String AUTHORIZATION_PARAMS = "{\"param\": {\"externalToken\": \"%s\"}}";
+
+ protected static final ObjectMapper objectMapper;
+
+ static {
+ objectMapper = new ObjectMapper();
+ objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ objectMapper.setDateFormat(new SimpleDateFormat("MM/dd/yyyy HH:mm"));
+ }
+
/**
* Constructor
*
@@ -78,7 +111,7 @@ public class JWTToken {
* @param secretEncoder encoder of secret
* @throws JWTException
*/
- public JWTToken(String token, String secret, String knownIssuers, SecretEncoder secretEncoder) throws JWTException{
+ public JWTToken(String token, String secret, String knownIssuers, String authorizationURL, SecretEncoder secretEncoder) throws JWTException{
if (token == null) {
logger.error("token can not be null");
throw new IllegalArgumentException("token can not be null");
@@ -95,8 +128,9 @@ public JWTToken(String token, String secret, String knownIssuers, SecretEncoder
this.knownIssuers.add(issuer.trim());
}
-
- setTokenAndSecret(token, secret);
+ this.authorizationURL = authorizationURL;
+ this.token = token;
+ this.secret = secret;
}
/**
@@ -105,7 +139,7 @@ public JWTToken(String token, String secret, String knownIssuers, SecretEncoder
* @param algorithm algorithm to be used
* @throws JWTException
*/
- protected void verify(Algorithm algorithm) throws JWTException {
+ protected void verifyToken(Algorithm algorithm) throws JWTException {
try {
Verification verification = JWT.require(algorithm);
@@ -135,20 +169,22 @@ protected void verify(Algorithm algorithm) throws JWTException {
}
/**
- * Set this JWT class besed on token string
+ * Verify this JWT class besed on token string
*
* @throws JWTException
*/
- protected void apply() throws JWTException {
- apply(this.encoder);
+ public JWTToken verify() throws JWTException {
+ return verify(this.encoder);
}
/**
- * Set this JWT class based on token string
+ * Verify this JWT class based on token string
+ *
* @param enc secret encoder
* @throws JWTException
*/
- protected void apply(SecretEncoder enc) throws JWTException {
+ public JWTToken verify(SecretEncoder enc) throws JWTException {
+ valid = false;
if (token == null)
throw new IllegalArgumentException("token must be specified.");
@@ -179,7 +215,6 @@ protected void apply(SecretEncoder enc) throws JWTException {
logger.info("Getting pub key from " + decodedJWT.getIssuer());
Jwk jwk = jwkProvider.get(decodedJWT.getKeyId());
RSAPublicKey publicKey = (RSAPublicKey) jwk.getPublicKey();
- logger.info("Pubkey: " + new String(publicKey.getEncoded()));
algorithm = Algorithm.RSA256(publicKey, null);
} catch (Exception e) {
@@ -203,8 +238,10 @@ protected void apply(SecretEncoder enc) throws JWTException {
} else {
throw new JWTException("Algorithm not supported: " + algorithmName);
}
- verify(algorithm);
+ verifyToken(algorithm);
decodedJWTApply(decodedJWT);
+ valid = true;
+ return this;
}
/**
@@ -254,6 +291,43 @@ protected Integer calcExpirySeconds(Integer exp, Integer iat) {
return exp - issuedAt;
}
+ /**
+ * Refresh jwt from authorizationUrl
+ *
+ * @return this instance
+ * @throws Exception if any error occurs
+ */
+ public JWTToken refresh() throws Exception {
+ if (authorizationURL == null || "".equals(authorizationURL))
+ throw new JWTException("Please set authorizationUrl");
+
+ logger.info("Refresh token from this url: " + authorizationURL);
+ DefaultHttpClient httpClient = new DefaultHttpClient();
+ String newToken;
+ try {
+ URI authorizationUri = new URI(this.authorizationURL);
+ HttpPost httpPost = new HttpPost(authorizationUri);
+ httpPost.addHeader(HttpHeaders.CONTENT_TYPE, "application/json");
+
+ StringEntity body = new StringEntity(String.format(AUTHORIZATION_PARAMS, token));
+ httpPost.setEntity(body);
+ HttpResponse response = httpClient.execute(httpPost);
+ HttpEntity entity = response.getEntity();
+ if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
+ throw new JWTEndpointException(String.format(ERROR_MESSAGE_FORMAT, authorizationUri,
+ response.getStatusLine().getStatusCode(),
+ getErrorMessage(response.getStatusLine().getStatusCode())));
+ }
+
+ JsonNode result = objectMapper.readTree(entity.getContent());
+ newToken = result.path("result").path("content").path("token").asText();
+ } finally {
+ httpClient.getConnectionManager().shutdown();
+ }
+ setTokenAndSecret(newToken, secret);
+ return this;
+ }
+
public String getUserId() {
return userId;
}
@@ -345,6 +419,18 @@ public String getToken() {
return token;
}
+ public String getAuthorizationURL() {
+ return authorizationURL;
+ }
+
+ public void setAuthorizationURL(String authorizationURL) {
+ this.authorizationURL = authorizationURL;
+ }
+
+ public boolean isValid() {
+ return valid;
+ }
+
/**
* Set new token
*
@@ -358,7 +444,7 @@ public void setTokenAndSecret(String token, String secret) throws JWTException {
}
this.token = token;
this.secret = secret;
- apply();
+ verify();
}
public static class SecretEncoder {
diff --git a/token.properties.docker b/token.properties.docker
index dff2d3332..c98b64de6 100644
--- a/token.properties.docker
+++ b/token.properties.docker
@@ -326,7 +326,7 @@
@CLIENT_SECRET_AUTH0@ = ZEEIRf_aLhvbYymAMTFefoEJ_8y7ELrUaboMTmE5fQoJXEo7sxxyg8IW6gtbyKuT
@REG_SERVER_NAME@= tc.cloud.topcoder.com
@LDAP_AUTH0_CONNECTION_NAME@=vm-ldap-connection
-@JWT_VALID_ISSUERS@ = https://sma.auth0.com, https://newtc.auth0.com
+@JWT_VALID_ISSUERS@ = https://sma.auth0.com, https://newtc.auth0.com, https://topcoder-newauth.auth0.com/
@ApplicationServer.SSO_COOKIE_KEY@=tcsso_vm
@ApplicationServer.SSO_HASH_SECRET@=GKDKJF80dbdc541fe829898aa01d9e30118bab5d6b9fe94fd052a40069385f5628
@@ -336,12 +336,10 @@
# Direct API #
#####################################
@ApplicationServer.JWT_COOKIE_KEY@=tcjwt_vm
-@ApplicationServer.JWT_V3_COOKIE_KEY@=v3jwt
@memberSearchApiUrl@=https://tc-api.cloud.topcoder.com:8443/v3/members/_suggest/
@groupMemberSearchApiUrl@=https://cockpit.cloud.topcoder.com/direct/group/member?handle=
@groupMemberApiUrl@=http://tc-api.cloud.topcoder.com:8080/v3/groups/%d/members
@directChallengeServicesApiUrl@=http://api.topcoder-dev.com/v3/direct/challenges
-@authorizationUrl@=http://192.168.31.105:8084/v3/authorizations
-@ssoLoginUrl@=https://topcoder-dev.com/login/
+@authorizationUrl@=https://api.topcoder-dev.com/v3/authorizations
@userGroupsApiEndpoint@=http://tc-api.cloud.topcoder.com:8080/v3/groups
diff --git a/token.properties.example b/token.properties.example
index 9f5824dea..c306d821d 100644
--- a/token.properties.example
+++ b/token.properties.example
@@ -302,8 +302,6 @@
@ApplicationServer.SSO_DOMAIN@=topcoder.com
@ApplicationServer.JWT_COOKIE_KEY@=tcjwt
-@ApplicationServer.JWT_V3_COOKIE_KEY@=v3jwt
-
#######################################
# securityGroupApplicationContext.xml #
@@ -401,5 +399,4 @@
@groupMemberApiUrl@=http://172.18.0.1:8080/v3/groups/%d/members
@directChallengeServicesApiUrl@=http://api.topcoder-dev.com/v3/direct/challenges
@authorizationUrl@=http://api.topcoder-dev.com/v3/authorizations
-@ssoLoginUrl@=https://topcoder-dev.com/login/
@userGroupsApiEndpoint@=http://172.18.0.1:8080/v3/groups
\ No newline at end of file