This guide outlines essential best practices and potential pitfalls when implementing the OAuth Authorization Code Grant and token refresh process with Perk's OAuth server.
1. Initial token acquisition
- Grant type: Use the
authorization_codegrant type to initiate the flow. - Result: This process yields an
access_tokenand arefresh_token. access_tokenuse: Theaccess_tokenis the key used to access Perk's APIs.access_tokenlifetime: Theaccess_tokenis short-lived and expires after 1 hour.refresh_tokenuse: Therefresh_tokenis used to acquire a new refresh and access token.refresh_tokenlifetime: Therefresh_tokenexpires 30 days from the time of issuance. The oldrefresh_tokenused to acquire the new token pair is revoked after 2 minutes.
2. Token refresh strategy
Since the access_token is short-lived, implement a robust refresh strategy:
- When to refresh: Acquire a new token pair before the current
access_tokenexpires (or immediately upon receiving an API error indicating an expired token). Periodically refreshing tokens in the background is also acceptable, but beware that defects in the refresh process or network errors risk losing a significant number of tokens. - Grant type: Use the
refresh_tokengrant at the token endpoint for this process.
Refresh-and-rotate policy
Perk's token policy: every successful request to the token endpoint returns a new access_token and a new refresh_token pair.
- Persistence: The newly issued
refresh_tokenmust be reliably persisted immediately upon receipt, replacing the old one. If the newrefresh_tokenisn't stored, the integration loses the ability to access the API once the old token expires. - Grace period: Perk allows a 2-minute grace period to retry calling the token endpoint with the same
refresh_token. This mitigates transient network issues where you successfully requested the token but failed to receive or fully process the response.
Example integration issues and mitigation
Lost token (failure to persist)
A failure can occur between receiving the new token pair and successfully storing it. If this happens, your application still has the old refresh_token, but the new one is lost forever, and the old one is effectively invalidated by the server.
Pseudocode example:
current_token = retrieve_persisted_refresh_token()
# Successful acquisition of new token
new_refresh_token, new_access_token = request_new_tokens(current_token)
# This operation fails
do_something_that_can_fail()
# The new token is never persisted, leading to a permanent failure.
persist_token_pair(new_refresh_token, new_access_token)Mitigation: Design your refresh logic to prioritize persisting the new key pair. Treat persistence failure as a severe error that requires immediate alerting.
Concurrent refreshing (race condition)
If multiple application processes or threads attempt to refresh the token simultaneously using the same (old) refresh_token, a race condition occurs.
- Result: Both requests to acquire a new token pair initially succeed. But because each successful call immediately invalidates the previously issued
refresh_token, only the last issued token will be long-lived and valid for the next refresh.
Pseudocode example:
# Process 1 starts
new_tokens_1 = request_new_tokens(old_refresh_token)
# Process 2 starts (using the same old_refresh_token)
new_tokens_2 = request_new_tokens(old_refresh_token)
# Process 2 wins the race and persists its token pair first
persist_tokens(new_tokens_2)
# Process 1 then persists its token pair
persist_tokens(new_tokens_1)
# With Perk's token refresh policy, both requests succeed but depending
# on the order in which the server processes the requests, one of the tokens
# will be expired after the grace period elapses.
# For the purposes of this example, the system persisted the tokens acquired
# by process 1, which will be expired.Mitigation: Ensure only one process can perform the refresh for a given connection at any given time. Use locking or other concurrency control measures such as a queue to serialize operations.

