Support automatic OAuth client-credentials token refresh - #838
Conversation
|
@PierreBtz this is in reference to #829. (heh, Captain obvious here. I missed the reference that is clearly at the top of the PR description :-D ) |
PierreBtz
left a comment
There was a problem hiding this comment.
Thanks for the contribution! I still have to run some tests on this PR but this looks very promising.
| * | ||
| * @see <a href="https://developer.zendesk.com/api-reference/ticketing/oauth/grant_type_tokens/"> | ||
| * OAuth grant type tokens</a> | ||
| * @since FIXME |
There was a problem hiding this comment.
| * @since FIXME | |
| * @since 1.6.0 |
There was a problem hiding this comment.
Updated all of these in 5ebbaaa. Thanks!
| * does nothing when there is nothing to prepare. | ||
| * | ||
| * @throws ZendeskOAuthException if minting fails | ||
| * @since FIXME |
There was a problem hiding this comment.
| * @since FIXME | |
| * @since 1.6.0 |
| * Default requested token lifetime. 30 minutes: short enough to limit the exposure of a leaked | ||
| * token, long enough to keep minting infrequent. | ||
| * | ||
| * @since FIXME |
There was a problem hiding this comment.
| * @since FIXME | |
| * @since 1.6.0 |
| /** | ||
| * Default refresh threshold. Refreshes when the current token has half its lifetime left. | ||
| * | ||
| * @since FIXME |
There was a problem hiding this comment.
| * @since FIXME | |
| * @since 1.6.0 |
| * @param clientSecret the OAuth client's secret | ||
| * @param scope space-separated scopes to request, for example {@code "tickets:read"} | ||
| * @return this builder instance | ||
| * @since FIXME |
There was a problem hiding this comment.
| * @since FIXME | |
| * @since 1.6.0 |
| * Supplies a currently-usable bearer token. Called on every request from many threads at once, so | ||
| * implementations must be thread-safe and may block while a token is minted. | ||
| * | ||
| * @since FIXME |
There was a problem hiding this comment.
| * @since FIXME | |
| * @since 1.6.0 |
| * not handed out. | ||
| * </ol> | ||
| * | ||
| * @since FIXME |
There was a problem hiding this comment.
| * @since FIXME | |
| * @since 1.6.0 |
| /** | ||
| * An immutable OAuth access token with the instants it was issued and expires. | ||
| * | ||
| * @since FIXME |
There was a problem hiding this comment.
| * @since FIXME | |
| * @since 1.6.0 |
| /** | ||
| * Acquires a brand-new access token. Does no caching, no coordination and no retry. | ||
| * | ||
| * @since FIXME |
There was a problem hiding this comment.
| * @since FIXME | |
| * @since 1.6.0 |
|
|
||
| public Zendesk build() { | ||
| if (oauthClientCredentialsConfigured) { | ||
| Objects.requireNonNull(oauthClientId, "OAuth client id cannot be null"); |
There was a problem hiding this comment.
Note that a blank ("") oauthClientId would pass this check, yet would not be valid and fail at runtime on the first mint.
There was a problem hiding this comment.
Thanks! Added blank checks for all of the new OAuth fields in 2be8014.
| private Future<Result> startMintingLeader( | ||
| ExecutorService pool, TokenProvider provider, FakeMinter minter) { | ||
| var leader = pool.submit(() -> call(provider)); | ||
| await().atMost(5, TimeUnit.SECONDS).until(() -> minter.threadsInsideMint.get() == 1); |
There was a problem hiding this comment.
There is a problem with this line if you run this test class and RealSmokeTest together:
ERROR] org.zendesk.client.v2.SharedFutureTokenProviderTest.failedMintExpectSameExceptionForAllAwaiters -- Time elapsed: 0.001 s <<< ERROR!
java.lang.IllegalArgumentException: Timeout (5 seconds) must be greater than the poll delay (10 seconds).
at org.awaitility.core.ConditionFactory.generateConditionSettings(ConditionFactory.java:1141)
at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:1129)
at org.zendesk.client.v2.SharedFutureTokenProviderTest.startMintingLeader(SharedFutureTokenProviderTest.java:507)
at org.zendesk.client.v2.SharedFutureTokenProviderTest.failedMintExpectSameExceptionForAllAwaiters(SharedFutureTokenProviderTest.java:231)
This is because RealSmokeTest globally sets a custom poll value that conflicts with the timeout you chose here:
There was a problem hiding this comment.
Ah I see, thanks for fixing this up.
Thanks @PierreBtz for the feedback and the prep. I've addressed your feedback and re-ran |
Summary
Adds support for Zendesk's OAuth
client_credentialsgrant so aZendeskclient can mint and refresh short-lived access tokens instead of requiring a pre-minted OAuth token.Addresses #829.
Changes
Commit 1: Base implementation
HttpTokenMinterclass for minting OAuth tokens, taking care to prevent credential leaks.SharedFutureTokenProviderclass for handling thread-safe token caching and refresh.Zendesk.Builderconfiguration.Zendesk#warmUp()for clients who would like to mint the OAuth token ahead of the first request.ZendeskOAuthExceptionwhen no usable token remains.Commit 2: Add backoff on refresh failures
SharedFutureTokenProviderto suppress proactive mint attempts for 10 seconds after a failed mint attempt while a usable cached token remains.Validation
mvn verifyusing JDK 11.References: