[OAuth2] Enable configurable early token refresh in Java Client
Motivation
In some client use cases, it is helpful to start attempting to refresh the OAuth2 token before it has expired. This PR adds that functionality.
The core addition is the ability to refresh the OAuth2 token in the background without affecting the current token. This will improve stability for OAuth2 users, especially if/when their IDP is unavailable.
Modifications
- Add a
ScheduledThreadPoolExecutorto theAuthenticationOAuth2and schedule refresh token tasks to refresh a token before it has expired. - Ensure that the refreshing is thread safe.
- Add tests to cover the new cases.
- Add documentation.
Verifying this change
This PR includes new tests. There are also existing tests that cover some of the changes.
Does this pull request potentially affect one of the following parts:
This PR changes the default behavior of the AuthenticationOAuth2 class and it also adds a new configuration value for end users. By default, it does not change the current behavior.
Documentation
- [x]
doc
I added docs.
@lhotari - I agree that we need to take care of the life cycle of the thread used for these refresh token commands. In my most recent commit, I changed the behavior so that the application can either supply an executor, or the OAuth2 class will create one (assuming that the feature is enabled, which it is not by default). The one downside here is that this means the feature is not available for brokers, because they create the AuthenticationOAuth2 class via reflection, and the configure method only takes strings. I think we should consider updating how the client authentication providers are configured and then it will probably be easier to use this feature when loading via reflection.
I think that the way to specify the refresh interval by using the "early_token_refresh_percent" configuration parameter is not well suited for all use cases.
Would you mind clarifying this use case with an example? On one hand, I accept that percent may be slightly less straight forward, but on the other hand, I think it handles certain edge cases really well. For example, each retrieved token can have a unique expires_in value. A percentage naturally handles this variability. Further, there is no guarantee that the min and max refresh interval that you described will fall within the expires_in value. Let me know what you think.
I think that the way to specify the refresh interval by using the "early_token_refresh_percent" configuration parameter is not well suited for all use cases.
Would you mind clarifying this use case with an example? On one hand, I accept that percent may be slightly less straight forward, but on the other hand, I think it handles certain edge cases really well. For example, each retrieved token can have a unique
expires_invalue. A percentage naturally handles this variability. Further, there is no guarantee that the min and max refresh interval that you described will fall within theexpires_invalue. Let me know what you think.
The use case would be that you want to maximize the time that a token is active at all times. The reason to do this is that if the identity provider becomes unavailable, there is less risk the whole system becomes unavailable because of the identity provider being unavailable. The system will tolerate a long downtime when the tokens are always active for the maximum period of time. The tradeoff is that there will be more token refreshes made towards the identity provider.
You might want to refresh the token every 10 minutes regardless of the validity of the token, given that the token is valid for more than 10 minutes. The solution I proposed wasn't probably the best way to address this use case.
Another person might want to refresh the token 10 minutes before the validity of the token expires, regardless of how long the token is valid.
For the above usecases, I would assume that configuring the solution would be possible with 2 parameters (naming is hard, so the names are still bad): "refresh before expiration duration" "minimum token usage duration"
The problem with the 10 minutes before token expires example is the case where the token is valid for less than 10 minutes. That's why it is necessary to have a second parameter to define how long the token is kept used until a refresh is made.
Let's say that the user has set "refresh before expiration duration" to 10 minutes and "minimum token usage duration" to 2 minutes. If the returned token is valid for 10 minutes, it would start the refresh after 2 minutes.
I simply don't see a use case for the earlyTokenRefreshPercent way of configuring the refresh scheduling. In the requirement we have, it's about exact times instead of percentages. I think that percentages would be confusing for users. "refresh before expiration duration" and "minimum token usage duration" parameters would be easier to understand.
@lhotari - thanks for clarifying your point. I hadn't thought of the use case where a user has a refresh period that is independent of the token's time to live. Of the two parameters, which should take precedence? I think we should use the minimum duration resulting from either minimum token usage duration or refresh before expiration duration. The one case that is not covered is when the token's time to live is shorter than these two parameters. We'll need a default behavior in that case. This is where a percentage would be valuable. The current code attempts a refresh when 90% of the tokens time to live has passed. We could use that percent, or use a conservative 50%. How do you think we should handle this edge case?
The pr had no activity for 30 days, mark with Stale label.
The pr had no activity for 30 days, mark with Stale label.
@michaeljmarshall This PR is likely beyond stale. Would you please close.