MadKudu/node-hubspot

AccessToken expires_in

Closed this issue · 5 comments

After the Oauth flow the hubspot object does not contain the accessToken "expires_in" data.
Such data is useful for setting the local cache lifetime properly

Hi @antoniofarina, is this issue still relevant, I'm sure that expires_in in the place. Could you please check if you still experiencing an issue?

Hi, yes it still occurs

This is my hubspot object resulting after calling await hubspot.refreshAccessToken()

Client { _events: [Object: null prototype] { apiCall: [Function] }, _eventsCount: 1, _maxListeners: undefined, qs: {}, auth: { bearer: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' }, clientId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', clientSecret: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', redirectUri: 'https://hb_proxy.translated.com:8443/oauth-callback', refreshToken: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', maxUsePercent: 90, baseUrl: 'https://api.hubapi.com', apiTimeout: 15000, apiCalls: 1, checkLimit: true, limiter: Bottleneck { _addToQueue: [Function: bound _addToQueue], datastore: 'local', connection: null, id: '<no-id>', rejectOnDrop: true, trackDoneStatus: false, Promise: [Function: Promise], _queues: Queues { on: [Function], once: [Function], removeAllListeners: [Function], Events: [Events], _length: 0, _lists: [Array] }, _scheduled: {}, _states: States { status: [Array], _jobs: {}, counts: [Array] }, _limiter: null, on: [Function], once: [Function], removeAllListeners: [Function], Events: Events { instance: [Circular], _events: {} }, _submitLock: Sync { schedule: [Function: bound schedule], name: 'submit', Promise: [Function: Promise], _running: 0, _queue: [DLList] }, _registerLock: Sync { schedule: [Function: bound schedule], name: 'register', Promise: [Function: Promise], _running: 0, _queue: [DLList] }, _store: LocalDatastore { instance: [Circular], storeOptions: [Object], clientId: '0bk48vzy3qjk', Promise: [Function: Promise], timeout: null, heartbeatInterval: 250, _lastReservoirIncrease: 1573050709391, _lastReservoirRefresh: 1573050709391, _nextRequest: 1573050709509.111, _running: 0, _done: 1, _unblockTime: 0, ready: [Promise], clients: {} } }, broadcasts: Broadcast { client: [Circular] }, campaigns: Campaign { client: [Circular] }, companies: Company { client: [Circular], properties: Properties { client: [Circular], groups: [Groups] } }, contacts: Contact { client: [Circular], properties: Properties { client: [Circular] } }, pages: Page { client: [Circular] }, deals: Deal { client: [Circular], properties: Properties { client: [Circular], groups: [DealGroups] } }, emails: Email { client: [Circular] }, engagements: Engagement { client: [Circular] }, files: File { client: [Circular] }, forms: Form { client: [Circular] }, integrations: Integrations { client: [Circular] }, lists: List { client: [Circular] }, oauth: OAuth { client: [Circular] }, owners: Owner { client: [Circular] }, pipelines: Pipeline { client: [Circular] }, timelines: Timeline { client: [Circular] }, subscriptions: Subscription { client: [Circular] }, workflows: Workflow { client: [Circular] }, crm: CRM { client: [Circular], associations: Associations { client: [Circular] } }, usageLimit: undefined, accessToken: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' }

Thanks, I see.
Both methods:

const tokens = await hubspot.refreshAccessToken();
const tokens = await hubspot.oauth.getAccessToken({code});

returns expires_in field alongside tokens. I would suggest operating with that value outside the hubspot wrapper, you could save it somewhere in the database/storage together with updated_at value and then check if the token is expired like following:

const isTokenExpired = (tokens) => {
  return Date.now() >= Date.parse(tokens.updated_at) + tokens.expires_in * 1000;
};

The main idea above it is keeping wrapper separate (not tightly connected) with Date representation/processing, authorization method and storege configuration.

I see, thank you.
In general, I think that, since the refreshAccessToken() and getAccessToken() methods "decorate" the self object with the properties refreshToken and accessToken (both returned by the methods above) it could be less misleading have a expiresIn property containing the value as resulted from the methods, and another property updatedAt containing the timestamp of the creation/update time.

I saw you put the thread in "ToDo": is this the solution you have n mind or something else?

thank you for your help

Hi @antoniofarina, actually that's just the list with pending issues/features.
Renaming it to 'Triage' to avoid any misunderstanding.
Currently playing with GitHub 'Projects' feature.
If you have some handy solution here or would like to contribute you are welcome. Thanks!