Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,18 @@ public Date getExpiry() {
return new Date(expiry.getTime());
}

/**
* Returns a copy of the issued at date time of the JWT SVID.
*
* @return a copy of the issued at date time of the JWT SVID, or {@code null} if the token
* does not have an 'iat' claim
*/
public Date getIssuedAt() {
// the 'iat' claim is optional in a JWT-SVID
if (issuedAt == null) {
return null;
}
// defensive copy to prevent exposing a mutable object
return new Date(issuedAt.getTime());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,13 @@ private static Set<String> getAudienceSet(String audience, String[] extraAudienc
}

private boolean isTokenPastHalfLifetime(JwtSvid jwtSvid) {
Object issuedAtClaim = jwtSvid.getClaims().get("iat");
if (!(issuedAtClaim instanceof Date)) {
Date issuedAt = jwtSvid.getIssuedAt();
if (issuedAt == null) {
return true;
}

long expiryTime = jwtSvid.getExpiry().getTime();
long issuedAtTime = ((Date) issuedAtClaim).getTime();
long issuedAtTime = issuedAt.getTime();
long halfLifeTime = expiryTime - (expiryTime - issuedAtTime) / 2;

return clock.instant().toEpochMilli() > halfLifeTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.KeyPair;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
Expand All @@ -23,6 +24,7 @@
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.fail;

class JwtSvidParseInsecureTest {
Expand Down Expand Up @@ -96,6 +98,40 @@ void testParseInsecure_nullAudience_throwsNullPointerException() throws JwtSvidE
}
}

@Test
void testParseInsecure_missingIssuedAt_getIssuedAtReturnsNull() throws JwtSvidException {
KeyPair key1 = TestUtils.generateECKeyPair(Curve.P_521);
SpiffeId spiffeId = TrustDomain.parse("test.domain").newSpiffeId("host");
Set<String> audience = Collections.singleton("audience");
Date expiration = new Date(System.currentTimeMillis() + 3600000);
JWTClaimsSet claims = TestUtils.buildJWTClaimSet(audience, spiffeId.toString(), expiration);

JwtSvid jwtSvid = JwtSvid.parseInsecure(TestUtils.generateToken(claims, key1, "authority1"), audience);

assertNull(jwtSvid.getIssuedAt());
}

@Test
void testParseInsecure_withIssuedAt_getIssuedAtReturnsCopy() throws JwtSvidException {
KeyPair key1 = TestUtils.generateECKeyPair(Curve.P_521);
SpiffeId spiffeId = TrustDomain.parse("test.domain").newSpiffeId("host");
Set<String> audience = Collections.singleton("audience");
Date issuedAt = new Date((System.currentTimeMillis() / 1000) * 1000);
Date expiration = new Date(issuedAt.getTime() + 3600000);
JWTClaimsSet claims = new JWTClaimsSet.Builder()
.subject(spiffeId.toString())
.audience(new ArrayList<>(audience))
.issueTime(issuedAt)
.expirationTime(expiration)
.build();

JwtSvid jwtSvid = JwtSvid.parseInsecure(TestUtils.generateToken(claims, key1, "authority1"), audience);

assertEquals(issuedAt, jwtSvid.getIssuedAt());
jwtSvid.getIssuedAt().setTime(0);
assertEquals(issuedAt, jwtSvid.getIssuedAt());
}

static Stream<Arguments> provideSuccessScenarios() {
KeyPair key1 = TestUtils.generateECKeyPair(Curve.P_521);
KeyPair key2 = TestUtils.generateECKeyPair(Curve.P_521);
Expand Down
Loading