Remove options to add IP address in JWT auth token. Fixes #2938

This commit is contained in:
Tim Donohue
2021-03-03 11:48:02 -06:00
parent 05b80bd941
commit 4efe92e23d
5 changed files with 15 additions and 81 deletions

View File

@@ -98,12 +98,6 @@ public abstract class JWTTokenHandler {
*/
protected abstract String getTokenExpirationConfigurationKey();
/**
* Get the configuration property key for the include ip.
* @return the configuration property key
*/
protected abstract String getTokenIncludeIPConfigurationKey();
/**
* Get the configuration property key for the encryption enable setting.
* @return the configuration property key
@@ -227,10 +221,6 @@ public abstract class JWTTokenHandler {
return secret;
}
public boolean getIncludeIP() {
return configurationService.getBooleanProperty(getTokenIncludeIPConfigurationKey(), true);
}
public long getExpirationPeriod() {
return configurationService.getLongProperty(getTokenExpirationConfigurationKey(), 1800000);
}
@@ -288,7 +278,7 @@ public abstract class JWTTokenHandler {
if (ePerson == null || StringUtils.isBlank(ePerson.getSessionSalt())) {
return false;
} else {
JWSVerifier verifier = new MACVerifier(buildSigningKey(request, ePerson));
JWSVerifier verifier = new MACVerifier(buildSigningKey(ePerson));
//If token is valid and not expired return eperson in token
Date expirationTime = jwtClaimsSet.getExpirationTime();
@@ -347,7 +337,7 @@ public abstract class JWTTokenHandler {
SignedJWT signedJWT = new SignedJWT(
new JWSHeader(JWSAlgorithm.HS256), claimsSet);
JWSSigner signer = new MACSigner(buildSigningKey(request, ePerson));
JWSSigner signer = new MACSigner(buildSigningKey(ePerson));
signedJWT.sign(signer);
return signedJWT;
}
@@ -385,18 +375,18 @@ public abstract class JWTTokenHandler {
* this way the key is always long enough for the HMAC using SHA-256 algorithm.
* More information: https://tools.ietf.org/html/rfc7518#section-3.2
*
* @param request
* @param ePerson
* @return
* @param ePerson currently authenticated EPerson
* @return signing key for token
*/
protected String buildSigningKey(HttpServletRequest request, EPerson ePerson) {
String ipAddress = "";
if (getIncludeIP()) {
ipAddress = getIpAddress(request);
}
return getJwtKey() + ePerson.getSessionSalt() + ipAddress;
protected String buildSigningKey(EPerson ePerson) {
return getJwtKey() + ePerson.getSessionSalt();
}
/**
* Get IP Address of client. Only used for logging purposes at this time
* @param request current request
* @return IP address of client
*/
private String getIpAddress(HttpServletRequest request) {
return clientInfoService.getClientIp(request);
}

View File

@@ -30,11 +30,6 @@ public class LoginJWTTokenHandler extends JWTTokenHandler {
return "jwt.login.token.expiration";
}
@Override
protected String getTokenIncludeIPConfigurationKey() {
return "jwt.login.token.include.ip";
}
@Override
protected String getEncryptionEnabledConfigurationKey() {
return "jwt.login.encryption.enabled";

View File

@@ -45,7 +45,7 @@ public class ShortLivedJWTTokenHandler extends JWTTokenHandler {
if (ePerson == null || StringUtils.isBlank(ePerson.getSessionSalt())) {
return false;
} else {
JWSVerifier verifier = new MACVerifier(buildSigningKey(request, ePerson));
JWSVerifier verifier = new MACVerifier(buildSigningKey(ePerson));
//If token is valid and not expired return eperson in token
Date expirationTime = jwtClaimsSet.getExpirationTime();
@@ -82,11 +82,6 @@ public class ShortLivedJWTTokenHandler extends JWTTokenHandler {
return "jwt.shortLived.token.expiration";
}
@Override
protected String getTokenIncludeIPConfigurationKey() {
return "jwt.shortLived.token.include.ip";
}
@Override
protected String getEncryptionEnabledConfigurationKey() {
return "jwt.shortLived.encryption.enabled";

View File

@@ -476,42 +476,7 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
}
@Test
public void testReuseTokenWithDifferentIPWhenIPStored() throws Exception {
// Enable IP storage in JWT login token
configurationService.setProperty("jwt.login.token.include.ip", true);
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(get("/api/authn/status"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.okay", is(true)))
.andExpect(jsonPath("$.authenticated", is(true)))
.andExpect(jsonPath("$.type", is("status")));
// Verify a different IP address (behind a proxy, i.e. X-FORWARDED-FOR)
// is *not* able to authenticate with same token
getClient(token).perform(get("/api/authn/status")
.header("X-FORWARDED-FOR", "1.1.1.1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.okay", is(true)))
.andExpect(jsonPath("$.authenticated", is(false)))
.andExpect(jsonPath("$.type", is("status")));
// Verify a different IP address is *not* able to authenticate with same token
getClient(token).perform(get("/api/authn/status")
.with(ip("1.1.1.1")))
.andExpect(status().isOk())
.andExpect(jsonPath("$.okay", is(true)))
.andExpect(jsonPath("$.authenticated", is(false)))
.andExpect(jsonPath("$.type", is("status")));
}
@Test
public void testReuseTokenWithDifferentIPWhenIPNotStored() throws Exception {
// Disable IP storage in JWT login token
configurationService.setProperty("jwt.login.token.include.ip", false);
public void testReuseTokenWithDifferentIP() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(get("/api/authn/status"))
@@ -523,6 +488,8 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
// Verify a different IP address (behind a proxy, i.e. X-FORWARDED-FOR)
// is able to authenticate with same token
// NOTE: We allow tokens to be used across several IPs to support environments where your IP is not static.
// Also keep in mind that if a token is used from an untrusted Origin, it will be blocked (see prior test).
getClient(token).perform(get("/api/authn/status")
.header("X-FORWARDED-FOR", "1.1.1.1"))
.andExpect(status().isOk())

View File

@@ -74,13 +74,6 @@ jwt.login.compression.enabled = true
# Expiration time of a token in milliseconds
jwt.login.token.expiration = 1800000
# Restrict tokens to a specific ip-address to prevent theft/session hijacking. This is achieved by making the ip-address
# a part of the JWT siging key. If this property is set to false then the ip-address won't be used as part of
# the signing key of a jwt token and tokens can be shared over multiple ip-addresses.
# For security reasons, this defaults to true
jwt.login.token.include.ip = true
#---------------------------------------------------------------#
#---Stateless JWT Authentication for downloads of bitstreams----#
#----------------------among other things-----------------------#
@@ -105,9 +98,3 @@ jwt.shortLived.compression.enabled = true
# Expiration time of a token in milliseconds
jwt.shortLived.token.expiration = 2000
# Restrict tokens to a specific ip-address to prevent theft/session hijacking. This is achieved by making the ip-address
# a part of the JWT siging key. If this property is set to false then the ip-address won't be used as part of
# the signing key of a jwt token and tokens can be shared over multiple ip-addresses.
# For security reasons, this defaults to true
jwt.shortLived.token.include.ip = true