33 */
44package com .topcoder .direct .services .view .action ;
55
6- import com .topcoder .direct .services .configs .ServerConfiguration ;
76import com .topcoder .direct .services .view .dto .contest .ContestStatus ;
8- import com .topcoder .direct .services .view .dto .my .SingleRestResult ;
9- import com .topcoder .direct .services .view .dto .my .Token ;
107import com .topcoder .direct .services .view .dto .project .ProjectBriefDTO ;
11- import com .topcoder .direct .services .view .exception .JwtAuthenticationException ;
128import com .topcoder .direct .services .view .util .DataProvider ;
139import com .topcoder .direct .services .view .util .DirectUtils ;
10+ import com .topcoder .direct .services .view .util .JwtTokenUpdater ;
1411import com .topcoder .security .TCSubject ;
15- import org .apache .commons .codec .binary .Base64 ;
1612import org .apache .http .HttpEntity ;
1713import org .apache .http .HttpHeaders ;
1814import org .apache .http .HttpResponse ;
1915import org .apache .http .HttpStatus ;
2016import org .apache .http .client .methods .HttpGet ;
21- import org .apache .http .client .methods .HttpPost ;
2217import org .apache .http .client .utils .URIBuilder ;
23- import org .apache .http .entity .StringEntity ;
2418import org .apache .http .impl .client .DefaultHttpClient ;
2519import org .apache .log4j .Logger ;
26- import org .apache .struts2 .ServletActionContext ;
2720import org .codehaus .jackson .JsonNode ;
2821import org .codehaus .jackson .map .DeserializationConfig ;
2922import org .codehaus .jackson .map .ObjectMapper ;
3023
31- import javax .servlet .http .Cookie ;
3224import java .io .UnsupportedEncodingException ;
3325import java .net .URI ;
3426import java .net .URISyntaxException ;
3527import java .net .URLEncoder ;
36- import java .nio .charset .StandardCharsets ;
3728import java .text .SimpleDateFormat ;
38- import java .util .*;
29+ import java .util .ArrayList ;
30+ import java .util .LinkedHashMap ;
31+ import java .util .List ;
32+ import java .util .Map ;
3933
4034/**
4135 * <p>
@@ -108,11 +102,6 @@ public abstract class ServiceBackendDataTablesAction extends AbstractAction {
108102 */
109103 private String serviceURL ;
110104
111- /**
112- * authorization Url
113- */
114- private String authorizationURL ;
115-
116105 /**
117106 * The challenge types options in filter panel
118107 *
@@ -196,11 +185,6 @@ public abstract class ServiceBackendDataTablesAction extends AbstractAction {
196185 */
197186 private String endDateTo ;
198187
199- /**
200- * ssoLogin Url
201- */
202- private String ssoLoginUrl ;
203-
204188 /**
205189 * The max pagination size.
206190 */
@@ -227,14 +211,14 @@ public abstract class ServiceBackendDataTablesAction extends AbstractAction {
227211 protected static final String ERROR_MESSAGE_FORMAT = "Service URL:%s, HTTP Status Code:%d, Error Message:%s" ;
228212
229213 /**
230- * URI params for refresh token
214+ * The jackson object mapping which is used to deserialize json return from API to domain model.
231215 */
232- private final String AUTHORIZATION_PARAMS = "{ \" param \" : { \" externalToken \" : \" %s \" }}" ;
216+ protected static final ObjectMapper objectMapper ;
233217
234218 /**
235- * The jackson object mapping which is used to deserialize json return from API to domain model.
219+ * JwtTokenUpdater
236220 */
237- protected static final ObjectMapper objectMapper ;
221+ private JwtTokenUpdater jwtTokenUpdater ;
238222
239223 /**
240224 * <p>A static <code>Map</code> mapping the existing contest statuses to their textual presentations.</p>
@@ -339,19 +323,10 @@ protected JsonNode getJsonResultFromAPI(URI apiEndPoint) throws Exception {
339323 // specify the get request
340324 HttpGet getRequest = new HttpGet (apiEndPoint );
341325
342- Cookie jwtCookieV3 = DirectUtils .getCookieFromRequest (ServletActionContext .getRequest (),
343- ServerConfiguration .JWT_V3_COOKIE_KEY );
344- Cookie jwtCookieV2 = DirectUtils .getCookieFromRequest (ServletActionContext .getRequest (),
345- ServerConfiguration .JWT_COOOKIE_KEY );
346-
347- if (jwtCookieV2 == null ) {
348- throw new JwtAuthenticationException ("Please re-login" );
349- }
350-
351- validateCookieV2V3 (jwtCookieV2 ,jwtCookieV3 );
326+ String token = jwtTokenUpdater .check ().getToken ();
352327
353328 getRequest .setHeader (HttpHeaders .AUTHORIZATION ,
354- "Bearer " + jwtCookieV3 . getValue () );
329+ "Bearer " + token );
355330
356331 getRequest .addHeader (HttpHeaders .ACCEPT , "application/json" );
357332
@@ -728,143 +703,11 @@ public void setEndDateTo(String endDateTo) {
728703 this .endDateTo = endDateTo ;
729704 }
730705
731- /**
732- * Getter for {@link #authorizationURL}
733- * @return authorizationURL
734- */
735- public String getAuthorizationURL () {
736- return authorizationURL ;
706+ public JwtTokenUpdater getJwtTokenUpdater () {
707+ return jwtTokenUpdater ;
737708 }
738709
739- /**
740- * Setter for {@link #authorizationURL}
741- * @param authorizationURL
742- */
743- public void setAuthorizationURL (String authorizationURL ) {
744- this .authorizationURL = authorizationURL ;
745- }
746-
747- /**
748- * Get Full SSO login url
749- * @return
750- */
751- public String getSsoLoginUrl () {
752- try {
753- URIBuilder builder = new URIBuilder (ssoLoginUrl );
754- builder .addParameter ("next" , ServletActionContext .getRequest ().getRequestURL ().toString ());
755- return builder .build ().toString ();
756- } catch (Exception e ) {
757- return ssoLoginUrl ;
758- }
759- }
760-
761- /**
762- * Setter {@link #ssoLoginUrl}
763- *
764- * @param ssoLoginUrl
765- */
766- public void setSsoLoginUrl (String ssoLoginUrl ) {
767- this .ssoLoginUrl = ssoLoginUrl ;
768- }
769-
770- /**
771- * Refresh token from API endpoint
772- *
773- * @param oldToken
774- * @return
775- * @throws Exception
776- */
777- private Token getRefreshTokenFromApi (String oldToken ) throws Exception {
778- DefaultHttpClient httpClient = new DefaultHttpClient ();
779- SingleRestResult <Token > resultToken = null ;
780- try {
781- URI authorizationUri = new URI (getAuthorizationURL ());
782- HttpPost httpPost = new HttpPost (authorizationUri );
783- httpPost .addHeader (HttpHeaders .CONTENT_TYPE , "application/json" );
784-
785- StringEntity body = new StringEntity (String .format (AUTHORIZATION_PARAMS , oldToken ));
786- httpPost .setEntity (body );
787- HttpResponse response = httpClient .execute (httpPost );
788- HttpEntity entity = response .getEntity ();
789- if (response .getStatusLine ().getStatusCode () != HttpStatus .SC_OK ) {
790- throw new JwtAuthenticationException (String .format (ERROR_MESSAGE_FORMAT , authorizationUri ,
791- response .getStatusLine ().getStatusCode (),
792- getErrorMessage (response .getStatusLine ().getStatusCode ())));
793- }
794-
795- JsonNode result = objectMapper .readTree (entity .getContent ());
796- resultToken = objectMapper .readValue (result .get ("result" ),
797- objectMapper .getTypeFactory ().constructParametricType (SingleRestResult .class , Token .class ));
798- } finally {
799- httpClient .getConnectionManager ().shutdown ();
800- }
801- return resultToken .getContent ();
802- }
803-
804- /**
805- * Verify token.If token expired: refresh it
806- *
807- * @param tokenV3
808- * @param tokenV2
809- * @return
810- * @throws JwtAuthenticationException
811- */
812- private String getValidJwtToken (String tokenV3 , String tokenV2 ) throws JwtAuthenticationException {
813- String [] tokenSplit = tokenV3 .split ("\\ ." );
814- boolean valid = true ;
815- if (tokenSplit .length < 2 ) valid = false ;
816-
817- JsonNode jsonNode = null ;
818-
819- try {
820- if (valid ) {
821- StringBuffer payloadStr = new StringBuffer (tokenSplit [1 ]);
822- while (payloadStr .length () % 4 != 0 ) payloadStr .append ('=' );
823- String payload = new String (Base64 .decodeBase64 (payloadStr .toString ().getBytes (StandardCharsets .UTF_8 )));
824-
825- jsonNode = objectMapper .readValue (payload .toString (), JsonNode .class );
826-
827- long exp = jsonNode .get ("exp" ).getLongValue ();
828- Date expDate = new Date (exp * 1000 );
829- logger .info ("token expire: " + expDate );
830- if (expDate .before (new Date ())) valid = false ;
831- }
832-
833- if (!valid ) {
834- logger .info ("refresh new token for : " + tokenV2 );
835- Token newToken = getRefreshTokenFromApi (tokenV2 );
836- if (newToken == null || newToken .getToken ().isEmpty ()) {
837- throw new JwtAuthenticationException ("Invalid refresh token" );
838- }
839-
840- return newToken .getToken ();
841- }
842- } catch (Exception e ) {
843- throw new JwtAuthenticationException ("Failed to refresh toke through api, Please go to sso login page : " +
844- getSsoLoginUrl ());
845- }
846- return tokenV3 ;
847- }
848-
849- /**
850- * Validate cookie v2 and v3
851- *
852- * @param v2 cookie v2
853- * @param v3 cookie v3
854- * @throws Exception
855- */
856- protected void validateCookieV2V3 (Cookie v2 , Cookie v3 ) throws Exception {
857- String validToken = null ;
858- String v3Token = null ;
859- if (v3 == null ) {
860- validToken = getRefreshTokenFromApi (v2 .getValue ()).getToken ();
861- } else {
862- validToken = getValidJwtToken (v3 .getValue (), v2 .getValue ());
863- v3Token = v3 .getValue ();
864- }
865-
866- if (!validToken .equals (v3Token )) {
867- DirectUtils .addDirectCookie (ServletActionContext .getResponse (), ServerConfiguration .JWT_V3_COOKIE_KEY , validToken , -1 );
868- }
710+ public void setJwtTokenUpdater (JwtTokenUpdater jwtTokenUpdater ) {
711+ this .jwtTokenUpdater = jwtTokenUpdater ;
869712 }
870713}
0 commit comments