Skip to content
Support the creatorSupport

Authentication & token refresh

Uploads carry Authorization: Bearer <accessToken>. The token lives in secure storage on the device, never in the config, and a failed token never stops tracking: fixes keep being recorded and queued while uploads wait for a working token.

await LongPing.setAuthorization({
accessToken: session.accessToken,
// Optional: let the device renew the token by itself.
refreshToken: session.refreshToken,
refreshUrl: 'https://api.example.com/auth/refresh',
});

setAuthorization():

  • stores the credentials (iOS Keychain; Android: encrypted with a non-exportable Android Keystore key),
  • clears any “authorization required” state,
  • and triggers an upload straight away, skipping backoff and any auth pause.

Call it after login and whenever your app gets a new token. Call clearAuthorization() on logout.

The stored token wins over an Authorization header in http.headers.

When an upload gets 401 or 403 and a refreshUrl is stored, the device refreshes on its own:

  1. POST refreshUrl with refreshPayload as JSON, plus your refreshHeaders. The default payload is {"refresh_token": "{{refreshToken}}"}; {{refreshToken}} is replaced with the stored refresh token.
  2. Read access_token (or accessToken) and, optionally, a new refresh_token (or refreshToken) from the JSON reply, and store them.
  3. Retry the same batch once with the new token.

Your refresh endpoint can be as simple as:

POST /auth/refresh → 200
{ "access_token": "eyJhbGciOi…", "refresh_token": "r-9f2c…" }

Custom payloads work too, for endpoints that expect other field names:

await LongPing.setAuthorization({
accessToken,
refreshToken,
refreshUrl: 'https://auth.example.com/oauth/token',
refreshPayload: {
grant_type: 'refresh_token',
refresh_token: '{{refreshToken}}',
client_id: 'driver-app',
},
refreshHeaders: { 'X-Client': 'driver-app' },
});

If there is no refreshUrl, or the refresh fails:

  • State.authorizationRequired becomes true,
  • the authorization event fires with { status, error },
  • the records stay in the queue,
  • uploads pause until you call setAuthorization(), or for 15 minutes, whichever comes first,
  • location keeps recording.

Listen for it and get the app a new token:

LongPing.onAuthorization(async ({ status, error }) => {
console.warn('upload auth failed', status, error);
const token = await refreshSessionSomehow(); // your auth flow
if (token) await LongPing.setAuthorization({ accessToken: token });
});

setAuthorization(), clearAuthorization() and the authorization event are about upload credentials. Location permission is handled by requestPermission() and reported by getProviderState() and onProviderChange.

The iOS Keychain survives an uninstall. Long Ping wipes its stored credentials on the first launch after a (re)install, so a reinstalled app never uploads with a previous user’s token. Call setAuthorization() after login as usual.