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
6 changes: 6 additions & 0 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ The JWT token may include DateNumber fields that can be used to validate that th
boolean isExpired = jwt.isExpired(10); // 10 seconds leeway
```

You can also check whether the token will expire within a given interval from now. This is useful when the app wants to proactively refresh the token before it expires. If the `"exp"` claim is missing, this returns `false`.

```java
boolean expiringSoon = jwt.expiresIn(60); // true if the token expires within the next 60 seconds
```


## Private Claims

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ JWT jwt = new JWT(token);
String issuer = jwt.getIssuer(); //get registered claims
String claim = jwt.getClaim("isAdmin").asString(); //get custom claims
boolean isExpired = jwt.isExpired(10); // Do time validation with 10 seconds leeway
boolean expiringSoon = jwt.expiresIn(60); // true if the token expires within the next 60 seconds
```

A `DecodeException` will raise with a detailed message if the token has:
Expand Down
21 changes: 21 additions & 0 deletions lib/src/main/java/com/auth0/android/jwt/JWT.java
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,27 @@ public boolean isExpired(long leeway) {
return !expValid || !iatValid;
}

/**
* Validates whether this JWT will expire within the given number of seconds from now.
* Useful when the app wants to refresh the token before its expiration time.
*
* @param seconds the interval in seconds from now to check the expiration against. Must be a positive value.
* @return true if the token expires within the given interval, or false otherwise. If the "exp" claim is missing, returns false.
*/
public boolean expiresIn(long seconds) {
if (seconds < 0) {
throw new IllegalArgumentException("The seconds must be a positive value.");
}

if (payload.exp == null) {
return false;
}

long todayTime = (long) (Math.floor(new Date().getTime() / 1000) * 1000);
Date futureDate = new Date(todayTime + seconds * 1000);
return !futureDate.before(payload.exp);
}

/**
* Returns the String representation of this JWT.
*
Expand Down
32 changes: 32 additions & 0 deletions lib/src/test/java/com/auth0/android/jwt/JWTTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,38 @@ public void shouldThrowIfLeewayIsNegative() {
jwt.isExpired(-1);
}

@Test
public void shouldNotExpireInIntervalWhenExpClaimIsMissing() {
JWT jwt = customTimeJWT(null, null);
assertThat(jwt.expiresIn(60), is(false));
}

@Test
public void shouldNotExpireInIntervalWhenExpiryIsBeyondInterval() {
JWT jwt = customTimeJWT(null, new Date().getTime() + 5000);
assertThat(jwt.expiresIn(2), is(false));
}

@Test
public void shouldExpireInIntervalWhenExpiryIsWithinInterval() {
JWT jwt = customTimeJWT(null, new Date().getTime() + 2000);
assertThat(jwt.expiresIn(5), is(true));
}

@Test
public void shouldExpireInIntervalWhenAlreadyExpired() {
JWT jwt = customTimeJWT(null, new Date().getTime() - 2000);
assertThat(jwt.expiresIn(0), is(true));
}

@Test
public void shouldThrowIfExpiresInSecondsIsNegative() {
exception.expect(IllegalArgumentException.class);
exception.expectMessage("The seconds must be a positive value.");
JWT jwt = customTimeJWT(null, new Date().getTime() + 2000);
jwt.expiresIn(-1);
}

@SuppressWarnings("ConstantConditions")
@Test
public void shouldNotRemoveKnownPublicClaimsFromTree() {
Expand Down
Loading