KEYCLOAK-12960 Use Long for time based values in JsonWebToken
This commit is contained in:
parent
167f73f54e
commit
536824beb6
5 changed files with 106 additions and 28 deletions
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Reference in a new issue