Skip to content

Commit

Permalink
[HWORKS-992] Remove obsolete code for renewing JWT tokens (#1491)
Browse files Browse the repository at this point in the history
[HWORKS-992] Remove testing for renewal tokens
  • Loading branch information
kouzant authored Feb 20, 2024
1 parent 9e32b74 commit 654cc2a
Show file tree
Hide file tree
Showing 5 changed files with 5 additions and 179 deletions.
3 changes: 0 additions & 3 deletions hopsworks-IT/src/test/ruby/spec/jwt_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@
expect_status_details(200)
expect(headers["authorization"]).not_to be_nil
expect(headers["authorization"]).not_to be_empty
renew_tokens = json_body[:renewTokens]
expect(renew_tokens.length).to eql(5)
end

describe "#logged in as service user" do
Expand All @@ -57,7 +55,6 @@

post "#{ENV['HOPSWORKS_API']}/auth/service",
URI.encode_www_form({ email: "[email protected]", password: "admin"}), { content_type: 'application/x-www-form-urlencoded'}
@renew_tokens = json_body[:renewTokens]
@master_token = headers["authorization"].split[1].strip
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,11 @@
import io.hops.hopsworks.common.user.AuthController;
import io.hops.hopsworks.common.user.QrCode;
import io.hops.hopsworks.common.user.UsersController;
import io.hops.hopsworks.common.util.DateUtils;
import io.hops.hopsworks.common.util.Settings;
import io.hops.hopsworks.exceptions.HopsSecurityException;
import io.hops.hopsworks.exceptions.UserException;
import io.hops.hopsworks.jwt.Constants;
import io.hops.hopsworks.jwt.JWTController;
import io.hops.hopsworks.jwt.JsonWebToken;
import io.hops.hopsworks.jwt.annotation.JWTRequired;
import io.hops.hopsworks.jwt.exception.DuplicateSigningKeyException;
import io.hops.hopsworks.jwt.exception.InvalidationException;
Expand Down Expand Up @@ -93,12 +91,6 @@
import javax.ws.rs.core.SecurityContext;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand Down Expand Up @@ -230,18 +222,14 @@ public Response serviceLogin(@FormParam("email") String email, @FormParam("passw
if (!needLogin(request, null, user)) {
return Response.ok().build();
}

if (!userController.isUserInRole(user, "AGENT")) {
throw new HopsSecurityException(RESTCodes.SecurityErrorCode.REST_ACCESS_CONTROL, Level.FINE,
"Users are not allowed to access this endpoint, use auth/login instead",
"User " + user.getUsername() + " tried to login but they don't have AGENT role");
}
request.getSession();

Collection roles = user.getBbcGroupCollection();
if (roles == null || roles.isEmpty()) {
throw new UserException(RESTCodes.UserErrorCode.NO_ROLE_FOUND, Level.FINE);
}

statusValidator.checkStatus(user.getStatus());
String saltedPassword = authController.preLoginCheck(user, password, null);

Expand All @@ -251,47 +239,9 @@ public Response serviceLogin(@FormParam("email") String email, @FormParam("passw
authController.registerAuthenticationFailure(user);
throw new UserException(RESTCodes.UserErrorCode.AUTHENTICATION_FAILURE, Level.FINE, null, ex.getMessage(), ex);
}

// First generate the one-time tokens for renewal of master token
String renewalKeyName = jwtController.getServiceOneTimeJWTSigningKeyname(user.getUsername(),
request.getRemoteHost());
LocalDateTime masterExpiration = DateUtils.getNow().plus(settings.getServiceJWTLifetimeMS(), ChronoUnit.MILLIS);
LocalDateTime notBefore = jwtController.computeNotBefore4ServiceRenewalTokens(masterExpiration);
LocalDateTime expiresAt = notBefore.plus(settings.getServiceJWTLifetimeMS(), ChronoUnit.MILLIS);
List<String> userRoles = userUtilities.getUserRoles(user);

JsonWebToken renewalJWTSpec = new JsonWebToken();
renewalJWTSpec.setSubject(user.getUsername());
renewalJWTSpec.setIssuer(settings.getJWTIssuer());
renewalJWTSpec.setAudience(JWTHelper.SERVICE_RENEW_JWT_AUDIENCE);
renewalJWTSpec.setKeyId(renewalKeyName);
renewalJWTSpec.setNotBefore(DateUtils.localDateTime2Date(notBefore));
renewalJWTSpec.setExpiresAt(DateUtils.localDateTime2Date(expiresAt));

Map<String, Object> claims = new HashMap<>(4);
claims.put(Constants.RENEWABLE, false);
claims.put(Constants.EXPIRY_LEEWAY, 3600);
claims.put(Constants.ROLES, userRoles.toArray(new String[1]));

String[] oneTimeRenewalTokens = jwtController.generateOneTimeTokens4ServiceJWTRenewal(renewalJWTSpec, claims,
settings.getJWTSigningKeyName());

// Then generate the master service token
try {
String signingKeyID = jwtController.getSignKeyID(oneTimeRenewalTokens[0]);
claims.clear();
// The rest of JWT claims will be added by JWTHelper
claims.put(Constants.RENEWABLE, false);
claims.put(Constants.SERVICE_JWT_RENEWAL_KEY_ID, signingKeyID);
String token = jWTHelper.createToken(user, settings.getJWTIssuer(), claims);

ServiceJWTDTO renewTokensResponse = new ServiceJWTDTO();
renewTokensResponse.setRenewTokens(oneTimeRenewalTokens);
return Response.ok().header(AUTHORIZATION, Constants.BEARER + token).entity(renewTokensResponse).build();
} catch (Exception ex) {
jwtController.deleteSigningKey(renewalKeyName);
throw ex;
}

String token = jWTHelper.createToken(user, settings.getJWTIssuer(), null);
return Response.ok().header(AUTHORIZATION, Constants.BEARER + token).build();
}

@GET
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ public class Constants {
public static final String EXPIRY_LEEWAY = "expLeeway";
public static final String ROLES = "roles";
public static final String WWW_AUTHENTICATE_VALUE="Bearer realm=\"Cauth Realm\"";
public static final String SERVICE_JWT_RENEWAL_KEY_ID = "renewal_key_id";


public static final int DEFAULT_EXPIRY_LEEWAY = 60; //60 secs for exp
public static final boolean DEFAULT_RENEWABLE = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
Expand All @@ -55,7 +52,6 @@
import static io.hops.hopsworks.jwt.Constants.DEFAULT_EXPIRY_LEEWAY;
import static io.hops.hopsworks.jwt.Constants.DEFAULT_RENEWABLE;
import static io.hops.hopsworks.jwt.Constants.EXPIRY_LEEWAY;
import static io.hops.hopsworks.jwt.Constants.ONE_TIME_JWT_SIGNING_KEY_NAME;
import static io.hops.hopsworks.jwt.Constants.RENEWABLE;
import static io.hops.hopsworks.jwt.Constants.ROLES;

Expand Down Expand Up @@ -463,70 +459,6 @@ public String renewToken(String token, Date newExp, Date notBefore, boolean inva
return renewedToken;
}

public String getSignKeyID(String token) {
DecodedJWT jwt = decodeToken(token);
return jwt.getKeyId();
}

public String[] generateOneTimeTokens4ServiceJWTRenewal(JsonWebToken jwtSpecs, Map<String, Object> claims,
String defaultJWTSigningKeyName)
throws NoSuchAlgorithmException, SigningKeyNotFoundException {
String[] renewalTokens = new String[5];
SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(Constants.ONE_TIME_JWT_SIGNATURE_ALGORITHM);
String[] audienceArray = jwtSpecs.getAudience().toArray(new String[1]);
try {
renewalTokens[0] = createToken(jwtSpecs.getKeyId(), true, jwtSpecs.getIssuer(),
audienceArray, jwtSpecs.getExpiresAt(), jwtSpecs.getNotBefore(), jwtSpecs.getSubject(), claims,
algorithm);
} catch (DuplicateSigningKeyException ex) {
LOGGER.log(Level.FINE, "Signing key already exist for service JWT key " + jwtSpecs.getKeyId()
+ ". Removing old one");
if (defaultJWTSigningKeyName != null) {
if (!defaultJWTSigningKeyName.equals(jwtSpecs.getKeyId())
&& !ONE_TIME_JWT_SIGNING_KEY_NAME.equals(jwtSpecs.getKeyId())) {
deleteSigningKey(jwtSpecs.getKeyId());
}
}
try {
renewalTokens[0] = createToken(jwtSpecs.getKeyId(), true, jwtSpecs.getIssuer(),
audienceArray, jwtSpecs.getExpiresAt(), jwtSpecs.getNotBefore(), jwtSpecs.getSubject(), claims,
algorithm);
} catch (DuplicateSigningKeyException dskex) {
// This should never happen, we handle it above
}
}
for (int i = 1; i < renewalTokens.length; i++) {
try {
renewalTokens[i] = createToken(jwtSpecs.getKeyId(), false, jwtSpecs.getIssuer(),
audienceArray, jwtSpecs.getExpiresAt(), jwtSpecs.getNotBefore(), jwtSpecs.getSubject(), claims,
algorithm);
} catch (DuplicateSigningKeyException dskex) {
// This should never happen, we do not create new signing key here
}
}
return renewalTokens;
}

private Date localDateTime2Date(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}

public LocalDateTime computeNotBefore4ServiceRenewalTokens(LocalDateTime masterExpiration) {
LocalDateTime notBefore = null;
if (masterExpiration.minus(3L, ChronoUnit.MINUTES).isBefore(LocalDateTime.now())) {
notBefore = masterExpiration.minus(3L, ChronoUnit.MILLIS);
} else {
notBefore = masterExpiration.minus(3L, ChronoUnit.MINUTES);
}
return notBefore;
}

private static final String SERVICE_ONE_TIME_SIGNING_KEYNAME = "%s_%s__%d";
public String getServiceOneTimeJWTSigningKeyname(String username, String remoteHost) {
long now = System.currentTimeMillis();
return String.format(SERVICE_ONE_TIME_SIGNING_KEYNAME, username, remoteHost, now);
}

public Map<String, Object> addDefaultClaimsIfMissing(Map<String, Object> userClaims, boolean isRenewable, int leeway,
String[] roles) {
if (userClaims == null) {
Expand Down

0 comments on commit 654cc2a

Please sign in to comment.