CallBack API get access token timeout and recovery?

It seems that getting the accessToken for the callbackAPI is limited by to a timeout, somewhere around 60 second ?

Made several successful calls to obtain the AccessToken (as below), however after around 60 seconds an error is returned.

That means in the event that this fails, the 3rd party app basically is broken and cannot send any events because it can’;t get a callback AccessToken anymore.? The user of the app may not be aware of this.

Should the flow then be, that wen receiving the callback event, to make a call the callback to to get the accessToken, before returning from the call back event or it fails and is not successfull within the timeout period ? If yes, then what should be returned to the CallBack grant request if the token was not successfully obtained. Will ST then resend the Callback request?

success:
{‘headers’: {‘schema’: ‘st-schema’, ‘version’: ‘1.0’, ‘interactionType’: ‘accessTokenResponse’, ‘requestId’: ‘def-123-456’}, ‘callbackAuthentication’: {‘tokenType’: ‘Bearer’, ‘accessToken’: ‘eyJhbGciOiJIUzM4NCJ9.MTd…G8K’, ‘refreshToken’: ‘eyJhbG…73GfI’, ‘expiresIn’: 86400}}

Error:
{‘headers’: {‘schema’: ‘st-schema’, ‘version’: ‘1.0’, ‘interactionType’: ‘accessTokenRequest’, ‘requestId’: ‘def-123-456’}, ‘globalError’: {‘errorEnum’: ‘INVALID-CODE’, ‘detail’: ‘the provided code is invalid’}}

  1. You will get a call back token on subscribed events, this one is a short lived token that can be used to request information based on a received event.
  2. You will have a token that is issued along with a refresh token. You need to manage these tokens for all of your out of band requests or updates. For token management, you should store the refresh token along with the expiresIn value. If the expires in value is greater than the length of time since it was issued, you will need to use the refresh token to obtain a new token.
1 Like

The situation I try to describe is before the 3rd party app received an access token:
Let me re-phrase the scenario again:

  1. User adds 3rd part cloud in the app
  2. 3rd party cloud receive grant call with code
  3. 3rd party all calls the St cloud to exchange for an access token - this fails for whatever reason
  4. After 10 minutes 3rd party cloud finally gets the call through
  5. ST cloud rejects the call because the code is expired (I have tested this and it’s true after 10 minutes)
  6. Now the integration cycle has failed. The user sees the devices in the app, but the 3rd party cloud has no access token for callbacks .

After calling the callback for a refresh, It seems the Refresh token is changed for every new access token refresh. Thus, if for some reason the client makes a refresh token request and fails to receive a response or an DB update for whatever reason, the 3rd party service cannot use the callback API anymore and the user of the app is not aware of the broken integration that state callback wont come through…

One more question: Is the access token per integration (OAuth session) or at the g lobal level (that is all OAath session should use the same access/ refresh token pair) ? currently I create an accesstoken for each user session (Oauth code grant flow) and this session is deleted after a call to the integration deleted event, and thus for each session I retrieve and store an state callback access and refresh token.

Here is an excerpt from IFTT describing the same problem.
Please confirm if a refresh token is immediately expired after a refresh call ?

Authentication

Q: Why does my API fail the ‘Ensure older refresh token does not expire immediately’ test?

The process of making the refresh token network request, waiting for the response and writing it to our database is inherently non-atomic.

To illustrate a scenario where this could be a problem: you receive our request, expire the token at that moment, but the token never makes it back to us. We now have a situation where the refresh token is invalid.

Because IFTTT users expect Applets to run in the background, it is difficult to notify them and ask to re-authenticate. By requiring that refresh tokens don’t expire immediately we allow ourselves a small window to re-request a new token if for some reason it doesn’t make it to our database.

Yes it is. Once you refresh a token, you will be issued a new token and a new refresh token. This is pretty standard oAuth flow.

it’s might be dangerous if older refresh tokens are invalidated. Google does not issue refresh tokens for callabcks and Alexa callbacks do not change the refresh token. As IFTTT also indicated: To illustrate a scenario where this could be a problem: you receive our request, expire the token at that moment, but the token never makes it back to us. We now have a situation where the refresh token is invalid. I have had this discussion with Google developers as well and they recommend to not expire the refresh token on the 3rd party service. thus being it industry standard (w/o allowing the some older refresh tokens) might be put up for discussion. Some argue that refresh token only should change for a new Oauth2 session, but most Ouath2 flows that requires user intervention. Ref: https://auth0.com/learn/refresh-tokens/

The tokens sent during callbacks are very short lived and do not count towards the app token or the refresh token. The callback token is meant for an immediate usage if a response is required to the callback. The the refresh token last for 30 days.

More detailed information on token usage and handling is here:

1 Like

© 2019 SmartThings, Inc. All Rights Reserved. Terms of Use | Privacy Policy

SmartThings; SmartApps®; Physical Graph; Hello, Home; and Hello, Smart Home are all trademarks of the SmartThings, Inc.