Skip to content

Commit f93db75

Browse files
feat: add authenticator invalidate (SHOP-231)
1 parent 12f248a commit f93db75

2 files changed

Lines changed: 95 additions & 2 deletions

File tree

smartling-api-commons/src/main/java/com/smartling/api/v2/client/auth/Authenticator.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,19 +116,26 @@ boolean isRefreshable()
116116
return refreshExpiresAt > clock.currentTimeMillis();
117117
}
118118

119+
public synchronized void invalidate()
120+
{
121+
this.authentication = null;
122+
this.expiresAt = -1;
123+
this.refreshExpiresAt = -1;
124+
}
125+
119126
private synchronized String getAccessTokenInternal()
120127
{
121128
this.authentication = api.authenticate(new AuthenticationRequest(userIdentifier, userSecret));
122129
this.expiresAt = authentication.getExpiresIn() * 1000 + System.currentTimeMillis();
123-
this.refreshExpiresAt = authentication.getRefreshExpiresIn() * 100 + System.currentTimeMillis();
130+
this.refreshExpiresAt = authentication.getRefreshExpiresIn() * 1000 + System.currentTimeMillis();
124131
return authentication.getAccessToken();
125132
}
126133

127134
private synchronized String refreshAccessToken()
128135
{
129136
this.authentication = api.refresh(new AuthenticationRefreshRequest(authentication.getRefreshToken()));
130137
this.expiresAt = authentication.getExpiresIn() * 1000 + System.currentTimeMillis();
131-
this.refreshExpiresAt = authentication.getRefreshExpiresIn() * 100 + System.currentTimeMillis();
138+
this.refreshExpiresAt = authentication.getRefreshExpiresIn() * 1000 + System.currentTimeMillis();
132139
return authentication.getAccessToken();
133140
}
134141
}

smartling-api-commons/src/test/java/com/smartling/api/v2/client/auth/AuthenticatorTest.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,90 @@ public void isRefreshableExpired()
141141
when(clock.currentTimeMillis()).thenReturn(REFRESH_TOKEN_TTL * 1000 + System.currentTimeMillis());
142142
assertFalse(authenticator.isRefreshable());
143143
}
144+
145+
@Test
146+
public void invalidateClearsToken()
147+
{
148+
when(clock.currentTimeMillis()).thenReturn(System.currentTimeMillis());
149+
authenticator.getAccessToken();
150+
assertTrue(authenticator.isValid());
151+
152+
authenticator.invalidate();
153+
154+
assertFalse(authenticator.isValid());
155+
assertFalse(authenticator.isRefreshable());
156+
}
157+
158+
@Test
159+
public void getAccessTokenAfterInvalidateReAuthenticates()
160+
{
161+
when(clock.currentTimeMillis()).thenReturn(System.currentTimeMillis());
162+
authenticator.getAccessToken();
163+
authenticator.invalidate();
164+
authenticator.getAccessToken();
165+
166+
verify(authenticationApi, times(2)).authenticate(any(AuthenticationRequest.class));
167+
verify(authenticationApi, never()).refresh(any(AuthenticationRefreshRequest.class));
168+
}
169+
170+
@Test
171+
public void getAccessTokenRefreshesAtExactExpiryBoundary()
172+
{
173+
Authentication shortLivedAuth = new Authentication("accessToken", "refreshToken", 480, 21600, "bearer");
174+
Authentication refreshedAuth = new Authentication("newAccessToken", "newRefreshToken", 480, 21600, "bearer");
175+
176+
when(authenticationApi.authenticate(any(AuthenticationRequest.class))).thenReturn(shortLivedAuth);
177+
when(authenticationApi.refresh(any(AuthenticationRefreshRequest.class))).thenReturn(refreshedAuth);
178+
179+
authenticator.getAccessToken();
180+
181+
when(clock.currentTimeMillis()).thenReturn(System.currentTimeMillis() + 480_000L);
182+
183+
String token = authenticator.getAccessToken();
184+
185+
assertEquals(refreshedAuth.getAccessToken(), token);
186+
verify(authenticationApi, times(1)).authenticate(any(AuthenticationRequest.class));
187+
verify(authenticationApi, times(1)).refresh(any(AuthenticationRefreshRequest.class));
188+
}
189+
190+
@Test
191+
public void getAccessTokenRefreshesJustBeforeRefreshTokenExpiry()
192+
{
193+
Authentication shortLivedAuth = new Authentication("accessToken", "refreshToken", 480, 21600, "bearer");
194+
Authentication refreshedAuth = new Authentication("newAccessToken", "newRefreshToken", 480, 21600, "bearer");
195+
196+
when(authenticationApi.authenticate(any(AuthenticationRequest.class))).thenReturn(shortLivedAuth);
197+
when(authenticationApi.refresh(any(AuthenticationRefreshRequest.class))).thenReturn(refreshedAuth);
198+
199+
authenticator.getAccessToken();
200+
201+
// Access token expired, refresh token still valid
202+
when(clock.currentTimeMillis()).thenReturn(System.currentTimeMillis() + 21_510_000L);
203+
204+
String token = authenticator.getAccessToken();
205+
206+
assertEquals(refreshedAuth.getAccessToken(), token);
207+
verify(authenticationApi, times(1)).authenticate(any(AuthenticationRequest.class));
208+
verify(authenticationApi, times(1)).refresh(any(AuthenticationRefreshRequest.class));
209+
}
210+
211+
@Test
212+
public void getAccessTokenRefreshesWhenAccessTokenExpiredButRefreshTokenValid()
213+
{
214+
Authentication shortLivedAuth = new Authentication("accessToken", "refreshToken", 480, 21600, "bearer");
215+
Authentication refreshedAuth = new Authentication("newAccessToken", "newRefreshToken", 480, 21600, "bearer");
216+
217+
when(authenticationApi.authenticate(any(AuthenticationRequest.class))).thenReturn(shortLivedAuth);
218+
when(authenticationApi.refresh(any(AuthenticationRefreshRequest.class))).thenReturn(refreshedAuth);
219+
220+
authenticator.getAccessToken();
221+
222+
when(clock.currentTimeMillis()).thenReturn(System.currentTimeMillis() + 600_000L);
223+
224+
String token = authenticator.getAccessToken();
225+
226+
assertEquals(refreshedAuth.getAccessToken(), token);
227+
verify(authenticationApi, times(1)).authenticate(any(AuthenticationRequest.class));
228+
verify(authenticationApi, times(1)).refresh(any(AuthenticationRefreshRequest.class));
229+
}
144230
}

0 commit comments

Comments
 (0)