Skip to content

Commit

Permalink
Fixed issue with SsoAccessTokenProvider prematurely throwing ExpiredT…
Browse files Browse the repository at this point in the history
…okenException (#4157)

* Fixed issue with SsoAccessTokenProvider prematurely throwing ExpiredTokenException

* Update test case names to represent error scerarios
  • Loading branch information
joviegas committed Jul 5, 2023
1 parent 71ced35 commit 4633382
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 10 deletions.
6 changes: 6 additions & 0 deletions .changes/next-release/bugfix-AWSSingleSignon-5691a92.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "bugfix",
"category": "AWS Single Sign-on",
"contributor": "",
"description": "Fixed issue with SsoAccessTokenProvider prematurely throwing ExpiredTokenException."
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@

package software.amazon.awssdk.services.sso.internal;

import static java.time.temporal.ChronoUnit.MINUTES;

import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
Expand Down Expand Up @@ -81,7 +79,7 @@ private SdkToken getTokenFromJson(String json) {
}

private boolean tokenIsInvalid(String expirationTime) {
return Instant.now().isAfter(Instant.parse(expirationTime).minus(15, MINUTES));
return Instant.now().isAfter(Instant.parse(expirationTime));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import org.junit.jupiter.api.Test;

/**
Expand All @@ -40,7 +44,7 @@ public class SsoAccessTokenProviderTest {
private static final String WRONG_TOKEN_FILE_NAME = "wrong-token-file.json";

@Test
public void cachedTokenFile_correctFormat_resolveAccessTokenCorrectly() throws IOException {
void cachedTokenFile_correctFormat_resolveAccessTokenCorrectly() throws IOException {
String tokenFile = "{\n" +
"\"accessToken\": \"base64string\",\n" +
"\"expiresAt\": \"2090-01-01T00:00:00Z\",\n" +
Expand All @@ -53,7 +57,7 @@ public void cachedTokenFile_correctFormat_resolveAccessTokenCorrectly() throws I
}

@Test
public void cachedTokenFile_accessTokenMissing_throwNullPointerException() throws IOException {
void cachedTokenFile_accessTokenMissing_throwNullPointerException() throws IOException {
String tokenFile = "{\n" +
"\"expiresAt\": \"2090-01-01T00:00:00Z\",\n" +
"\"region\": \"us-west-2\", \n" +
Expand All @@ -65,7 +69,7 @@ public void cachedTokenFile_accessTokenMissing_throwNullPointerException() throw
}

@Test
public void cachedTokenFile_expiresAtMissing_throwNullPointerException() throws IOException {
void cachedTokenFile_expiresAtMissing_throwNullPointerException() throws IOException {
String tokenFile = "{\n" +
"\"accessToken\": \"base64string\",\n" +
"\"region\": \"us-west-2\", \n" +
Expand All @@ -78,7 +82,7 @@ public void cachedTokenFile_expiresAtMissing_throwNullPointerException() throws
}

@Test
public void cachedTokenFile_optionalRegionMissing_resolveAccessTokenCorrectly() throws IOException {
void cachedTokenFile_optionalRegionMissing_resolveAccessTokenCorrectly() throws IOException {
String tokenFile = "{\n" +
"\"accessToken\": \"base64string\",\n" +
"\"expiresAt\": \"2090-01-01T00:00:00Z\",\n" +
Expand All @@ -90,7 +94,7 @@ public void cachedTokenFile_optionalRegionMissing_resolveAccessTokenCorrectly()
}

@Test
public void cachedTokenFile_optionalStartUrlMissing_resolveAccessTokenCorrectly() throws IOException {
void cachedTokenFile_optionalStartUrlMissing_resolveAccessTokenCorrectly() throws IOException {
String tokenFile = "{\n" +
"\"accessToken\": \"base64string\",\n" +
"\"expiresAt\": \"2090-01-01T00:00:00Z\",\n" +
Expand All @@ -102,7 +106,7 @@ public void cachedTokenFile_optionalStartUrlMissing_resolveAccessTokenCorrectly(
}

@Test
public void cachedTokenFile_alreadyExpired_resolveAccessTokenCorrectly() throws IOException {
void cachedTokenFile_alreadyExpired_resolveAccessTokenCorrectly() throws IOException {
String tokenFile = "{\n" +
"\"accessToken\": \"base64string\",\n" +
"\"expiresAt\": \"2019-01-01T00:00:00Z\",\n" +
Expand All @@ -115,7 +119,7 @@ public void cachedTokenFile_alreadyExpired_resolveAccessTokenCorrectly() throws
}

@Test
public void cachedTokenFile_tokenFileNotExist_throwNullPointerException() throws IOException {
void cachedTokenFile_tokenFileNotExist_throwNullPointerException() throws IOException {
String tokenFile = "{\n" +
"\"accessToken\": \"base64string\",\n" +
"\"expiresAt\": \"2019-01-01T00:00:00Z\",\n" +
Expand All @@ -127,6 +131,44 @@ public void cachedTokenFile_tokenFileNotExist_throwNullPointerException() throws
assertThatThrownBy(() -> provider.resolveToken().token()).isInstanceOf(UncheckedIOException.class);
}

@Test
void cachedTokenFile_AboutToExpire_resolveAccessTokenCorrectly() throws IOException {
String tokenFile = String.format("{\n" +
"\"accessToken\": \"base64string\",\n" +
"\"expiresAt\": \"%s\",\n" +
"\"startUrl\": \""+ START_URL +"\"\n" +
"}", stringFormattedTime(Instant.now().plusSeconds(10)));
SsoAccessTokenProvider provider = new SsoAccessTokenProvider(
prepareTestCachedTokenFile(tokenFile, GENERATED_TOKEN_FILE_NAME));
assertThat(provider.resolveToken().token()).isEqualTo("base64string");
}

@Test
void cachedTokenFile_JustExpired_throwsExpiredTokenException() throws IOException {
String tokenFile = String.format("{\n" +
"\"accessToken\": \"base64string\",\n" +
"\"expiresAt\": \"%s\",\n" +
"\"startUrl\": \""+ START_URL +"\"\n" +
"}", stringFormattedTime(Instant.now()));
SsoAccessTokenProvider provider = new SsoAccessTokenProvider(
prepareTestCachedTokenFile(tokenFile, GENERATED_TOKEN_FILE_NAME));
assertThatThrownBy(() -> provider.resolveToken().token()).hasMessageContaining("The SSO session associated with this profile "
+ "has expired or is otherwise invalid.");
}

@Test
void cachedTokenFile_ExpiredFewSecondsAgo_throwsExpiredTokenException() throws IOException {
String tokenFile = String.format("{\n" +
"\"accessToken\": \"base64string\",\n" +
"\"expiresAt\": \"%s\",\n" +
"\"startUrl\": \""+ START_URL +"\"\n" +
"}", stringFormattedTime(Instant.now().minusSeconds(1)));
SsoAccessTokenProvider provider = new SsoAccessTokenProvider(
prepareTestCachedTokenFile(tokenFile, GENERATED_TOKEN_FILE_NAME));
assertThatThrownBy(() -> provider.resolveToken().token()).hasMessageContaining("The SSO session associated with this profile "
+ "has expired or is otherwise invalid.");
}

private Path prepareTestCachedTokenFile(String tokenFileContent, String generatedTokenFileName) throws IOException {
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
Path fileDirectory = fs.getPath("./foo");
Expand All @@ -142,4 +184,11 @@ private Path createTestCachedTokenFilePath(Path directory, String tokenFileName)
return directory.resolve(tokenFileName);
}

private String stringFormattedTime(Instant instant){
// Convert Instant to ZonedDateTime with UTC time zone
ZonedDateTime zonedDateTime = instant.atZone(ZoneOffset.UTC);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
return formatter.format(zonedDateTime);
}

}

0 comments on commit 4633382

Please sign in to comment.