Skip to content

Managing Access and Refresh Tokens

Handling tokens correctly is what keeps an integration running without repeatedly interrupting your customers. This page covers how NowInfinity tokens behave and what your integration needs to do with them.

Token lifetimes

TokenLifetimePurpose
Access token1 hourAuthenticates your API requests.
Refresh tokenUp to 30 daysObtains a new access token without user interaction.

Read expires_in from the token response rather than hard-coding the access token lifetime — it is returned with every token, and reading it means your integration keeps working if the configured lifetime changes.

Prerequisites

Before you begin:

  • Valid client credentials for the environment you are working in.
  • offline_access in your granted scope. Without it, no refresh token is issued.
  • An understanding of the Authorisation Code Flow.

Using access tokens

Send the access token as a Bearer token on every API request:

Authorization: Bearer {access_token}

Reuse the same access token for as many calls as you need until it expires. Track its expiry using the issuance time plus expires_in.

Do not request a new access token for every API call. It is unnecessary, slower, and puts avoidable load on the authorisation server.

Refresh tokens rotate

Refresh tokens are single-use. Each time you exchange one for a new access token, the response includes a new refresh token, and the one you just used is immediately invalidated.

Your integration must:

  1. Use the current refresh token to request a new access token.
  2. Store the new refresh token returned in the response.
  3. Discard the old one.

If you keep using the original refresh token, the second attempt fails with invalid_grant.

Refresh in one place only. If two workers, threads or scheduled jobs refresh the same token concurrently, one succeeds and invalidates the token the other is using — so the second fails with invalid_grant, and depending on how your code reacts you can lose the valid token entirely.

This is the most common cause of integrations that work in testing and fail under load. Serialise refreshes behind a lock, or handle refresh in a single dedicated process.

Refreshing a token

Send an HTTP POST to the token endpoint:

ParameterRequiredValue
grant_typeYesrefresh_token
refresh_tokenYesYour current refresh token
curl -X POST https://auth.nowinfinity-test.com.au/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token={current_refresh_token}" \
  -d "client_id={your_client_id}" \
  -d "client_secret={your_client_secret}"

The response contains a new access token and a new refresh token. Store both immediately.

Refresh proactively

Refresh before the access token expires rather than waiting for a 401. Refreshing a few minutes early avoids failed requests and retry logic you would otherwise have to write.

Storing tokens

  • Store both tokens in your backend. Never expose them to a browser, mobile client or log file.
  • Store the refresh token against the customer it belongs to. A refresh token is tied to the authorisation that produced it.
  • Persist the new refresh token before you use the new access token, so a crash mid-cycle does not leave you holding an invalidated token.

When refresh fails

A refresh token stops working when it expires, when it has already been used, or when the customer revokes your access. In each case the recovery is the same: start a new authorisation flow to obtain a fresh token pair.

Your integration should detect this and surface it to the customer as "reconnect your account", rather than retrying and failing silently.

Revoking a token

The authorisation server exposes a revocation endpoint, published as revocation_endpoint in the discovery document. Use it to invalidate a token when a customer disconnects your integration, rather than leaving a valid token outstanding until it expires.