Skip to content

Commit 3b47606

Browse files
committed
Set refreshOn in MI flows to half of token lifetime
1 parent 310cc07 commit 3b47606

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AcquireTokenByManagedIdentitySupplier.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class AcquireTokenByManagedIdentitySupplier extends AuthenticationResultSupplier
1313

1414
private static final Logger LOG = LoggerFactory.getLogger(AcquireTokenByManagedIdentitySupplier.class);
1515

16+
private static final int TWO_HOURS = 2*3600;
17+
1618
private ManagedIdentityParameters managedIdentityParameters;
1719

1820
AcquireTokenByManagedIdentitySupplier(ManagedIdentityApplication managedIdentityApplication, MsalRequest msalRequest) {
@@ -93,15 +95,27 @@ private AuthenticationResult fetchNewAccessTokenAndSaveToCache(TokenRequestExecu
9395
}
9496

9597
private AuthenticationResult createFromManagedIdentityResponse(ManagedIdentityResponse managedIdentityResponse) {
96-
long expiresOn = Long.valueOf(managedIdentityResponse.expiresOn);
97-
long refreshOn = expiresOn > 2 * 3600 ? (expiresOn / 2) : 0L;
98+
long expiresOn = Long.parseLong(managedIdentityResponse.expiresOn);
99+
long refreshOn = calculateRefreshOn(expiresOn);
100+
AuthenticationResultMetadata metadata = AuthenticationResultMetadata.builder()
101+
.refreshOn(refreshOn)
102+
.build();
98103

99104
return AuthenticationResult.builder()
100105
.accessToken(managedIdentityResponse.getAccessToken())
101106
.scopes(managedIdentityParameters.resource())
102107
.expiresOn(expiresOn)
103108
.extExpiresOn(0)
104109
.refreshOn(refreshOn)
110+
.metadata(metadata)
105111
.build();
106112
}
113+
114+
private long calculateRefreshOn(long expiresOn){
115+
long timestampSeconds = System.currentTimeMillis() / 1000;
116+
long expiresIn = expiresOn - timestampSeconds;
117+
118+
//The refreshOn value should be half the value of the token lifetime, if the lifetime is greater than two hours
119+
return expiresIn > TWO_HOURS ? (expiresIn / 2) + timestampSeconds : 0;
120+
}
107121
}

msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTests.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class ManagedIdentityTests {
4444
private static ManagedIdentityApplication miApp;
4545

4646
private String getSuccessfulResponse(String resource) {
47-
long expiresOn = Instant.now().plus(1, ChronoUnit.HOURS).getEpochSecond();
47+
long expiresOn = (System.currentTimeMillis() / 1000) + (24 * 3600);//A long-lived, 24 hour token
4848
return "{\"access_token\":\"accesstoken\",\"expires_on\":\"" + expiresOn + "\",\"resource\":\"" + resource + "\",\"token_type\":" +
4949
"\"Bearer\",\"client_id\":\"client_id\"}";
5050
}
@@ -222,6 +222,34 @@ void managedIdentityTest_UserAssigned_SuccessfulResponse(ManagedIdentitySourceTy
222222
verify(httpClientMock, times(1)).send(any());
223223
}
224224

225+
@Test
226+
void managedIdentityTest_RefreshOnHalfOfExpiresOn() throws Exception {
227+
//All managed identity flows use the same AcquireTokenByManagedIdentitySupplier where refreshOn is set,
228+
// so any of the MI options should let us verify that it's being set correctly
229+
IEnvironmentVariables environmentVariables = new EnvironmentVariablesHelper(ManagedIdentitySourceType.APP_SERVICE, appServiceEndpoint);
230+
ManagedIdentityApplication.setEnvironmentVariables(environmentVariables);
231+
ManagedIdentityClient.resetManagedIdentitySourceType();
232+
DefaultHttpClient httpClientMock = mock(DefaultHttpClient.class);
233+
234+
when(httpClientMock.send(expectedRequest(ManagedIdentitySourceType.APP_SERVICE, resource))).thenReturn(expectedResponse(200, getSuccessfulResponse(resource)));
235+
236+
miApp = ManagedIdentityApplication
237+
.builder(ManagedIdentityId.systemAssigned())
238+
.httpClient(httpClientMock)
239+
.build();
240+
241+
AuthenticationResult result = (AuthenticationResult) miApp.acquireTokenForManagedIdentity(
242+
ManagedIdentityParameters.builder(resource)
243+
.build()).get();
244+
245+
long timestampSeconds = (System.currentTimeMillis() / 1000);
246+
247+
assertNotNull(result.accessToken());
248+
assertEquals((result.expiresOn() - timestampSeconds)/2, result.refreshOn() - timestampSeconds);
249+
250+
verify(httpClientMock, times(1)).send(any());
251+
}
252+
225253
@ParameterizedTest
226254
@MethodSource("com.microsoft.aad.msal4j.ManagedIdentityTestDataProvider#createDataUserAssignedNotSupported")
227255
void managedIdentityTest_UserAssigned_NotSupported(ManagedIdentitySourceType source, String endpoint, ManagedIdentityId id) throws Exception {

0 commit comments

Comments
 (0)