3

We have an iOS app which communicates with a web-service.

It uses OAuth authentication (via AppAuth) with access_token and refresh_token. When short access_token expires, we need to refresh it using refresh_token.

We are now adding a Today Extension and want to make the extension communicate with a web-service too. But there is a problem – how to handle the renewal of the access/refresh token pair?

It seems like the main app might be sleeping when Today Extension is running, so sometimes there might be a situation when we want to refresh the access_token right from Today Extension. Since that invalidates the other refresh_token we have in the main app, it becomes very tricky to synchronize tokens back and forth.

Is there any established way to synchronize token refreshing? Or maybe we should reconsider our approach somehow?

We use Keychain to store and share tokens right now, that part works great. But refreshing and syncing of tokens is something we are having a hard time figuring out.

uson1x
  • 407
  • 3
  • 16
  • You meant "[...] that invalidates the other *`access_token`* [...]", right? – luk2302 Mar 14 '19 at 14:20
  • If you already use keychain to share the tokens what is stopping you form always trying the access_token in the keychain and if that is rejected because it is expired use the refresh_token from the keychain, get a new access_token and store that in the keychain!? – luk2302 Mar 14 '19 at 14:22
  • 1
    Racing conditions and speed concerns. What if both main app and app extension try to refresh the token simultaneously and write/read it from keychain? And I'm not sure if it's ok to access keychain so often (lesser concern)?. As for which token is invalidated – maybe both? Pretty sure you can't get a new `access_token` by using same `refresh_token` twice, although I haven't tested that. – uson1x Mar 14 '19 at 14:26
  • I understand both concerns. I personally would not worry about the race condition since in the worst case both apps get the expired token, retrieve a new one, and store the new tokens, one will "win" and store a valid token in the keychain. The fact that the other app has another access token should not matter. – luk2302 Mar 14 '19 at 14:30
  • The refresh_token should stay the same forever. Only the access_token expires and needs to be refreshed, the refresh_token is valid until explicitly revoked by whoever initially granted it to you. – luk2302 Mar 14 '19 at 14:31
  • Hm, I have just checked and I can see that with each request to refresh the token, the response contains new (changed) refresh_token. We use AppAuth + identityserver4 on backend. Could refresh token behavior be implementation-specific? – uson1x Mar 14 '19 at 14:37
  • Seems to be: https://tools.ietf.org/html/rfc6749#section-1.5 . That is not ideal... Then race conditions become a problem to think about, and I do not have an idea for that right now – luk2302 Mar 14 '19 at 14:42
  • Yeah... Well, thanks a lot for your time anyway! – uson1x Mar 14 '19 at 14:46
  • @uson1x I'm curious as to what solution you have come up to solve this issue. I'm currently facing the exact scenario. I can't use AppAuth library in app extension so I use token sharing via keychain as well. – Bryan P Feb 21 '20 at 11:12
  • @BryanP unfortunately, we did not solve this for our app, decided not to put any dynamic content into the extension. As I remember, one possible direction to explore was to use separate token for the extension. Also, it is actually possible to configure identityserver4 *not* to change `refresh_token` on token refresh, but to keep it the same. It could work to embrace the racing condition and let it refresh multiple times, as @luk2302 suggested. – uson1x Feb 24 '20 at 18:45
  • 1
    I see. What I did was to just share the database of both the main app and the today widget to get the data stored locally. – Bryan P Feb 27 '20 at 01:09

0 Answers0