nhost / nhost-dart

Nhost Dart & Flutter packages
https://nhost.io
MIT License
90 stars 33 forks source link

GQL subscription is using stale JWT after device idle (iOS) #21

Open shyndman opened 3 years ago

shyndman commented 3 years ago

@MaxSchilling has reported that his graphql client is making a request using a stale JWT after the Android device has been off for some amount of time.

After some research, I suspect that Android Doze suspending timers and network connections. When the app resumes, the websocket notices and begins reconnecting with the old JWT, which happens concurrently with the JWT refresh.

I'm confirming now. If correct, the solution is simple, because the way gql_websocket_link is configured gives us control over socket creation, and that API is async — we can keep it waiting for a JWT refresh.

elitan commented 3 years ago

We had a similar issue with the nhost-js-sdk.

This was our solution there:

https://github.com/nhost/nhost-js-sdk/blob/master/src/Auth.ts#L639-L650

shyndman commented 3 years ago

Yes! I saw that while porting, and do have questions about that (since people are now building for Flutter Web.)

But in this case, it's not exactly the same issue.

What I'm seeing is Android suspending all network activity while "dozing" (a state that is entered after a few minutes of the screen being off). In this state, application code continues to run, which includes timer callbacks (possibly at a reduced or less exact rate), but network requests never go out (so JWTs don't refresh), and websocket keep alives never come in (leading to socket disconnects+reconnection attempts).

When everything wakes back up, it's in a bad state, because you have a websocket queued up to send its initial payload (which will contain the "current", stale, JWT), and a JWT refresh queued up that whose response won't be received before that payload is sent.

MaxSchilling commented 3 years ago

It actually also occured on iOS

shyndman commented 3 years ago

Ah, well I believe it's even simpler in that case.

iOS standby mode is a lot like Doze from what I've read, but is even stricter. I should be able to repro the issues I've seen there with the same testbed.

Thank you for letting me know.