KEYCLOAK-12960 Use Long for time based values in JsonWebToken

This commit is contained in:
stianst 2020-02-14 11:37:16 +01:00 committed by Stian Thorgersen
parent 167f73f54e
commit 536824beb6
5 changed files with 106 additions and 28 deletions

View file

@ -17,6 +17,7 @@
package org.keycloak.representations; package org.keycloak.representations;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import org.keycloak.TokenCategory; import org.keycloak.TokenCategory;
@ -61,8 +62,7 @@ public class IDToken extends JsonWebToken {
@JsonProperty(NONCE) @JsonProperty(NONCE)
protected String nonce; protected String nonce;
@JsonProperty(AUTH_TIME) protected Long auth_time;
protected int authTime;
@JsonProperty(SESSION_STATE) @JsonProperty(SESSION_STATE)
protected String sessionState; protected String sessionState;
@ -149,12 +149,28 @@ public class IDToken extends JsonWebToken {
this.nonce = nonce; this.nonce = nonce;
} }
public int getAuthTime() { public Long getAuth_time() {
return authTime; return auth_time;
} }
/**
* @deprecated int will overflow with values after 2038. Use {@link #getAuth_time()} instead.
*/
@Deprecated
@JsonIgnore
public int getAuthTime() {
return auth_time != null ? auth_time.intValue() : 0;
}
public void setAuth_time(Long auth_time) {
this.auth_time = auth_time;
}
/**
* @deprecated int will overflow with values after 2038. Use {@link #setAuth_time(Long)} ()} instead.
*/
public void setAuthTime(int authTime) { public void setAuthTime(int authTime) {
this.authTime = authTime; this.auth_time = Long.valueOf(authTime);
} }
public String getSessionState() { public String getSessionState() {

View file

@ -41,12 +41,11 @@ import java.util.Map;
public class JsonWebToken implements Serializable, Token { public class JsonWebToken implements Serializable, Token {
@JsonProperty("jti") @JsonProperty("jti")
protected String id; protected String id;
@JsonProperty("exp")
protected int expiration; protected Long exp;
@JsonProperty("nbf") protected Long nbf;
protected int notBefore; protected Long iat;
@JsonProperty("iat")
protected int issuedAt;
@JsonProperty("iss") @JsonProperty("iss")
protected String issuer; protected String issuer;
@JsonProperty("aud") @JsonProperty("aud")
@ -70,33 +69,68 @@ public class JsonWebToken implements Serializable, Token {
return this; return this;
} }
public Long getExp() {
public int getExpiration() { return exp;
return expiration;
} }
/**
* @deprecated int will overflow with values after 2038. Use {@link #getExp()} instead.
*/
@Deprecated
@JsonIgnore
public int getExpiration() {
return exp != null ? exp.intValue() : 0;
}
public JsonWebToken exp(Long exp) {
this.exp = exp;
return this;
}
/**
* @deprecated int will overflow with values after 2038. Use {@link #exp(Long)} instead.
*/
public JsonWebToken expiration(int expiration) { public JsonWebToken expiration(int expiration) {
this.expiration = expiration; this.exp = Long.valueOf(expiration);
return this; return this;
} }
@JsonIgnore @JsonIgnore
public boolean isExpired() { public boolean isExpired() {
return Time.currentTime() > expiration; return exp != null && exp != 0 ? Time.currentTime() > exp : false;
} }
public Long getNbf() {
return nbf;
}
/**
* @deprecated int will overflow with values after 2038. Use {@link #getNbf()} instead.
*/
@Deprecated
@JsonIgnore
public int getNotBefore() { public int getNotBefore() {
return notBefore; return nbf != null ? nbf.intValue() : 0;
} }
public JsonWebToken nbf(Long nbf) {
this.nbf = nbf;
return this;
}
/**
* @deprecated int will overflow with values after 2038. Use {@link #nbf(Long)} instead.
*/
@Deprecated
@JsonIgnore
public JsonWebToken notBefore(int notBefore) { public JsonWebToken notBefore(int notBefore) {
this.notBefore = notBefore; this.nbf = Long.valueOf(notBefore);
return this; return this;
} }
@JsonIgnore @JsonIgnore
public boolean isNotBefore(int allowedTimeSkew) { public boolean isNotBefore(int allowedTimeSkew) {
return Time.currentTime() + allowedTimeSkew >= notBefore; return nbf != null ? Time.currentTime() + allowedTimeSkew >= nbf : true;
} }
/** /**
@ -111,11 +145,20 @@ public class JsonWebToken implements Serializable, Token {
@JsonIgnore @JsonIgnore
public boolean isActive(int allowedTimeSkew) { public boolean isActive(int allowedTimeSkew) {
return (!isExpired() || expiration == 0) && (isNotBefore(allowedTimeSkew) || notBefore == 0); return !isExpired() && isNotBefore(allowedTimeSkew);
} }
public Long getIat() {
return iat;
}
/**
* @deprecated int will overflow with values after 2038. Use {@link #getIat()} instead.
*/
@Deprecated
@JsonIgnore
public int getIssuedAt() { public int getIssuedAt() {
return issuedAt; return iat != null ? iat.intValue() : 0;
} }
/** /**
@ -123,12 +166,22 @@ public class JsonWebToken implements Serializable, Token {
*/ */
@JsonIgnore @JsonIgnore
public JsonWebToken issuedNow() { public JsonWebToken issuedNow() {
issuedAt = Time.currentTime(); iat = Long.valueOf(Time.currentTime());
return this; return this;
} }
public JsonWebToken iat(Long iat) {
this.iat = iat;
return this;
}
/**
* @deprecated int will overflow with values after 2038. Use {@link #iat(Long)} ()} instead.
*/
@Deprecated
@JsonIgnore
public JsonWebToken issuedAt(int issuedAt) { public JsonWebToken issuedAt(int issuedAt) {
this.issuedAt = issuedAt; this.iat = Long.valueOf(issuedAt);
return this; return this;
} }

View file

@ -46,7 +46,7 @@ public class DefaultActionTokenKey extends JsonWebToken implements ActionTokenKe
public DefaultActionTokenKey(String userId, String actionId, int absoluteExpirationInSecs, UUID actionVerificationNonce) { public DefaultActionTokenKey(String userId, String actionId, int absoluteExpirationInSecs, UUID actionVerificationNonce) {
this.subject = userId; this.subject = userId;
this.type = actionId; this.type = actionId;
this.expiration = absoluteExpirationInSecs; this.exp = Long.valueOf(absoluteExpirationInSecs);
this.actionVerificationNonce = actionVerificationNonce == null ? UUID.randomUUID() : actionVerificationNonce; this.actionVerificationNonce = actionVerificationNonce == null ? UUID.randomUUID() : actionVerificationNonce;
} }

View file

@ -222,6 +222,15 @@ public class AccessTokenTest extends AbstractKeycloakTest {
assertEquals(sessionId, token.getSessionState()); assertEquals(sessionId, token.getSessionState());
assertNull(token.getNbf());
assertEquals(0, token.getNotBefore());
assertNotNull(token.getIat());
assertEquals(token.getIat().intValue(), token.getIssuedAt());
assertNotNull(token.getExp());
assertEquals(token.getExp().intValue(), token.getExpiration());
assertEquals(1, token.getRealmAccess().getRoles().size()); assertEquals(1, token.getRealmAccess().getRoles().size());
assertTrue(token.getRealmAccess().isUserInRole("user")); assertTrue(token.getRealmAccess().isUserInRole("user"));

View file

@ -108,7 +108,7 @@ public class TokenIntrospectionTest extends AbstractTestRealmKeycloakTest {
assertEquals("test-app", jsonNode.get("client_id").asText()); assertEquals("test-app", jsonNode.get("client_id").asText());
assertTrue(jsonNode.has("exp")); assertTrue(jsonNode.has("exp"));
assertTrue(jsonNode.has("iat")); assertTrue(jsonNode.has("iat"));
assertTrue(jsonNode.has("nbf")); assertFalse(jsonNode.has("nbf"));
assertTrue(jsonNode.has("sub")); assertTrue(jsonNode.has("sub"));
assertTrue(jsonNode.has("aud")); assertTrue(jsonNode.has("aud"));
assertTrue(jsonNode.has("iss")); assertTrue(jsonNode.has("iss"));
@ -121,7 +121,7 @@ public class TokenIntrospectionTest extends AbstractTestRealmKeycloakTest {
assertEquals("test-app", rep.getClientId()); assertEquals("test-app", rep.getClientId());
assertEquals(jsonNode.get("exp").asInt(), rep.getExpiration()); assertEquals(jsonNode.get("exp").asInt(), rep.getExpiration());
assertEquals(jsonNode.get("iat").asInt(), rep.getIssuedAt()); assertEquals(jsonNode.get("iat").asInt(), rep.getIssuedAt());
assertEquals(jsonNode.get("nbf").asInt(), rep.getNotBefore()); assertEquals(jsonNode.get("nbf"), rep.getNbf());
assertEquals(jsonNode.get("sub").asText(), rep.getSubject()); assertEquals(jsonNode.get("sub").asText(), rep.getSubject());
List<String> audiences = new ArrayList<>(); List<String> audiences = new ArrayList<>();
@ -163,7 +163,7 @@ public class TokenIntrospectionTest extends AbstractTestRealmKeycloakTest {
assertEquals("test-app", jsonNode.get("client_id").asText()); assertEquals("test-app", jsonNode.get("client_id").asText());
assertTrue(jsonNode.has("exp")); assertTrue(jsonNode.has("exp"));
assertTrue(jsonNode.has("iat")); assertTrue(jsonNode.has("iat"));
assertTrue(jsonNode.has("nbf")); assertFalse(jsonNode.has("nbf"));
assertTrue(jsonNode.has("sub")); assertTrue(jsonNode.has("sub"));
assertTrue(jsonNode.has("aud")); assertTrue(jsonNode.has("aud"));
assertTrue(jsonNode.has("iss")); assertTrue(jsonNode.has("iss"));
@ -177,7 +177,7 @@ public class TokenIntrospectionTest extends AbstractTestRealmKeycloakTest {
assertEquals(jsonNode.get("session_state").asText(), rep.getSessionState()); assertEquals(jsonNode.get("session_state").asText(), rep.getSessionState());
assertEquals(jsonNode.get("exp").asInt(), rep.getExpiration()); assertEquals(jsonNode.get("exp").asInt(), rep.getExpiration());
assertEquals(jsonNode.get("iat").asInt(), rep.getIssuedAt()); assertEquals(jsonNode.get("iat").asInt(), rep.getIssuedAt());
assertEquals(jsonNode.get("nbf").asInt(), rep.getNotBefore()); assertEquals(jsonNode.get("nbf"), rep.getNbf());
assertEquals(jsonNode.get("iss").asText(), rep.getIssuer()); assertEquals(jsonNode.get("iss").asText(), rep.getIssuer());
assertEquals(jsonNode.get("jti").asText(), rep.getId()); assertEquals(jsonNode.get("jti").asText(), rep.getId());
assertEquals(jsonNode.get("typ").asText(), "Refresh"); assertEquals(jsonNode.get("typ").asText(), "Refresh");