Skip to content

Commit 4633382

Browse files
authored
Fixed issue with SsoAccessTokenProvider prematurely throwing ExpiredTokenException (#4157)
* Fixed issue with SsoAccessTokenProvider prematurely throwing ExpiredTokenException * Update test case names to represent error scerarios
1 parent 71ced35 commit 4633382

File tree

3 files changed

+63
-10
lines changed

3 files changed

+63
-10
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "bugfix",
3+
"category": "AWS Single Sign-on",
4+
"contributor": "",
5+
"description": "Fixed issue with SsoAccessTokenProvider prematurely throwing ExpiredTokenException."
6+
}

services/sso/src/main/java/software/amazon/awssdk/services/sso/internal/SsoAccessTokenProvider.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515

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

18-
import static java.time.temporal.ChronoUnit.MINUTES;
19-
2018
import java.io.IOException;
2119
import java.io.InputStream;
2220
import java.io.UncheckedIOException;
@@ -81,7 +79,7 @@ private SdkToken getTokenFromJson(String json) {
8179
}
8280

8381
private boolean tokenIsInvalid(String expirationTime) {
84-
return Instant.now().isAfter(Instant.parse(expirationTime).minus(15, MINUTES));
82+
return Instant.now().isAfter(Instant.parse(expirationTime));
8583
}
8684

8785
}

services/sso/src/test/java/software/amazon/awssdk/services/sso/internal/SsoAccessTokenProviderTest.java

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
import java.nio.file.FileSystem;
2828
import java.nio.file.Files;
2929
import java.nio.file.Path;
30+
import java.time.Instant;
31+
import java.time.ZoneOffset;
32+
import java.time.ZonedDateTime;
33+
import java.time.format.DateTimeFormatter;
3034
import org.junit.jupiter.api.Test;
3135

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

4246
@Test
43-
public void cachedTokenFile_correctFormat_resolveAccessTokenCorrectly() throws IOException {
47+
void cachedTokenFile_correctFormat_resolveAccessTokenCorrectly() throws IOException {
4448
String tokenFile = "{\n" +
4549
"\"accessToken\": \"base64string\",\n" +
4650
"\"expiresAt\": \"2090-01-01T00:00:00Z\",\n" +
@@ -53,7 +57,7 @@ public void cachedTokenFile_correctFormat_resolveAccessTokenCorrectly() throws I
5357
}
5458

5559
@Test
56-
public void cachedTokenFile_accessTokenMissing_throwNullPointerException() throws IOException {
60+
void cachedTokenFile_accessTokenMissing_throwNullPointerException() throws IOException {
5761
String tokenFile = "{\n" +
5862
"\"expiresAt\": \"2090-01-01T00:00:00Z\",\n" +
5963
"\"region\": \"us-west-2\", \n" +
@@ -65,7 +69,7 @@ public void cachedTokenFile_accessTokenMissing_throwNullPointerException() throw
6569
}
6670

6771
@Test
68-
public void cachedTokenFile_expiresAtMissing_throwNullPointerException() throws IOException {
72+
void cachedTokenFile_expiresAtMissing_throwNullPointerException() throws IOException {
6973
String tokenFile = "{\n" +
7074
"\"accessToken\": \"base64string\",\n" +
7175
"\"region\": \"us-west-2\", \n" +
@@ -78,7 +82,7 @@ public void cachedTokenFile_expiresAtMissing_throwNullPointerException() throws
7882
}
7983

8084
@Test
81-
public void cachedTokenFile_optionalRegionMissing_resolveAccessTokenCorrectly() throws IOException {
85+
void cachedTokenFile_optionalRegionMissing_resolveAccessTokenCorrectly() throws IOException {
8286
String tokenFile = "{\n" +
8387
"\"accessToken\": \"base64string\",\n" +
8488
"\"expiresAt\": \"2090-01-01T00:00:00Z\",\n" +
@@ -90,7 +94,7 @@ public void cachedTokenFile_optionalRegionMissing_resolveAccessTokenCorrectly()
9094
}
9195

9296
@Test
93-
public void cachedTokenFile_optionalStartUrlMissing_resolveAccessTokenCorrectly() throws IOException {
97+
void cachedTokenFile_optionalStartUrlMissing_resolveAccessTokenCorrectly() throws IOException {
9498
String tokenFile = "{\n" +
9599
"\"accessToken\": \"base64string\",\n" +
96100
"\"expiresAt\": \"2090-01-01T00:00:00Z\",\n" +
@@ -102,7 +106,7 @@ public void cachedTokenFile_optionalStartUrlMissing_resolveAccessTokenCorrectly(
102106
}
103107

104108
@Test
105-
public void cachedTokenFile_alreadyExpired_resolveAccessTokenCorrectly() throws IOException {
109+
void cachedTokenFile_alreadyExpired_resolveAccessTokenCorrectly() throws IOException {
106110
String tokenFile = "{\n" +
107111
"\"accessToken\": \"base64string\",\n" +
108112
"\"expiresAt\": \"2019-01-01T00:00:00Z\",\n" +
@@ -115,7 +119,7 @@ public void cachedTokenFile_alreadyExpired_resolveAccessTokenCorrectly() throws
115119
}
116120

117121
@Test
118-
public void cachedTokenFile_tokenFileNotExist_throwNullPointerException() throws IOException {
122+
void cachedTokenFile_tokenFileNotExist_throwNullPointerException() throws IOException {
119123
String tokenFile = "{\n" +
120124
"\"accessToken\": \"base64string\",\n" +
121125
"\"expiresAt\": \"2019-01-01T00:00:00Z\",\n" +
@@ -127,6 +131,44 @@ public void cachedTokenFile_tokenFileNotExist_throwNullPointerException() throws
127131
assertThatThrownBy(() -> provider.resolveToken().token()).isInstanceOf(UncheckedIOException.class);
128132
}
129133

134+
@Test
135+
void cachedTokenFile_AboutToExpire_resolveAccessTokenCorrectly() throws IOException {
136+
String tokenFile = String.format("{\n" +
137+
"\"accessToken\": \"base64string\",\n" +
138+
"\"expiresAt\": \"%s\",\n" +
139+
"\"startUrl\": \""+ START_URL +"\"\n" +
140+
"}", stringFormattedTime(Instant.now().plusSeconds(10)));
141+
SsoAccessTokenProvider provider = new SsoAccessTokenProvider(
142+
prepareTestCachedTokenFile(tokenFile, GENERATED_TOKEN_FILE_NAME));
143+
assertThat(provider.resolveToken().token()).isEqualTo("base64string");
144+
}
145+
146+
@Test
147+
void cachedTokenFile_JustExpired_throwsExpiredTokenException() throws IOException {
148+
String tokenFile = String.format("{\n" +
149+
"\"accessToken\": \"base64string\",\n" +
150+
"\"expiresAt\": \"%s\",\n" +
151+
"\"startUrl\": \""+ START_URL +"\"\n" +
152+
"}", stringFormattedTime(Instant.now()));
153+
SsoAccessTokenProvider provider = new SsoAccessTokenProvider(
154+
prepareTestCachedTokenFile(tokenFile, GENERATED_TOKEN_FILE_NAME));
155+
assertThatThrownBy(() -> provider.resolveToken().token()).hasMessageContaining("The SSO session associated with this profile "
156+
+ "has expired or is otherwise invalid.");
157+
}
158+
159+
@Test
160+
void cachedTokenFile_ExpiredFewSecondsAgo_throwsExpiredTokenException() throws IOException {
161+
String tokenFile = String.format("{\n" +
162+
"\"accessToken\": \"base64string\",\n" +
163+
"\"expiresAt\": \"%s\",\n" +
164+
"\"startUrl\": \""+ START_URL +"\"\n" +
165+
"}", stringFormattedTime(Instant.now().minusSeconds(1)));
166+
SsoAccessTokenProvider provider = new SsoAccessTokenProvider(
167+
prepareTestCachedTokenFile(tokenFile, GENERATED_TOKEN_FILE_NAME));
168+
assertThatThrownBy(() -> provider.resolveToken().token()).hasMessageContaining("The SSO session associated with this profile "
169+
+ "has expired or is otherwise invalid.");
170+
}
171+
130172
private Path prepareTestCachedTokenFile(String tokenFileContent, String generatedTokenFileName) throws IOException {
131173
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
132174
Path fileDirectory = fs.getPath("./foo");
@@ -142,4 +184,11 @@ private Path createTestCachedTokenFilePath(Path directory, String tokenFileName)
142184
return directory.resolve(tokenFileName);
143185
}
144186

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

0 commit comments

Comments
 (0)