Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAK-10780: add azure access token refresh logic #1441

Merged
merged 6 commits into from
May 24, 2024

Conversation

t-rana
Copy link
Contributor

@t-rana t-rana commented May 9, 2024

Azure Access token is valid for 1 hour only. Added code to check for token expiry every 4 minutes, and refresh the token when the same is close to expiry.

public void run() {
try {
log.debug("Checking for azure access token expiry at: {}", LocalDateTime.now());
OffsetDateTime tokenExpiryThreshold = OffsetDateTime.now().plusMinutes(5);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OffsetDateTime tokenExpiryThreshold = OffsetDateTime.now().plusMinutes(5);
OffsetDateTime tokenExpiryThreshold = OffsetDateTime.now().plusMinutes(20);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

azure identity serves the token from cache, and will only refresh the token when there are 5 minutes left in token expiry. so keeping a 20 minutes threshold will not help as the token will be served from cache only and will not be refreshed. hence i have taken a threshold of 5 minutes similar to what is being used in azure identity.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no cache in IdentityClient.authenticateWithClientSecret.
So the token will definitely be refreshed even at 20 minutes.
With 5 minutes there is a risk of a single transient failure causing token expiration.

Copy link
Contributor Author

@t-rana t-rana May 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification. In this case we should reduce the TOKEN_REFRESHER_DELAY to 1 minute so that even in the case of transient failures we will still successfully refresh before the token expires.

Copy link

@rootpea rootpea May 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively instead of ClientSecretCredential, you can create directly a ConfidentialClientApplication and set skipCache(true) in the parameters

// configure once, then store these for later use in the tokenrefresher:
        ConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplication
                .builder(clientId, ClientCredentialFactory.createFromSecret(clientSecret))
                .authority("https://login.microsoftonline.com/" + tenantId + "/")
                .build();

        ClientCredentialParameters clientCredentialParameters =
                ClientCredentialParameters.builder(Collections.singleton(AZURE_DEFAULT_SCOPE)).skipCache(true)
                        .tenant(IdentityUtil
                                .resolveTenantId(tenantId, new TokenRequestContext().addScopes(AZURE_DEFAULT_SCOPE), new IdentityClientOptions())).build();

// refreshing anytime:
        IAuthenticationResult authResult = confidentialClientApplication.acquireToken(clientCredentialParameters).join();
        AccessToken accessToken = new AccessToken(authResult.accessToken(), OffsetDateTime.ofInstant(authResult.expiresOnDate().toInstant(), ZoneOffset.UTC));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer the first way here since that is tested. Reduced the token refresh interval to 1 minute

log.debug("Checking for azure access token expiry at: {}", LocalDateTime.now());
OffsetDateTime tokenExpiryThreshold = OffsetDateTime.now().plusMinutes(5);
if (accessToken.getExpiresAt() != null && accessToken.getExpiresAt().isBefore(tokenExpiryThreshold)) {
log.info("Access token is about to expire (5 minutes or less) at: {}. New access token will be generated",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
log.info("Access token is about to expire (5 minutes or less) at: {}. New access token will be generated",
log.info("Access token is about to expire (20 minutes or less) at: {}. New access token will be generated",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above.

@smiroslav smiroslav merged commit c2e2cd7 into apache:trunk May 24, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants