How to timeout local session in Flutter, if the application is inactive for some duration?
Tags: flutter
Published: 2022-04-25 14:06:27

We might have noticed in banking and payment applications users will be redirected to the login page when the app is pushed to the background for some time or if the app hasn’t received any user interactions for some time.

If the application has user authentication with a web server, the session/token expires after some time while the app was in the background.


But relying only on session/token has some downsides i.e., the app has to communicate with a web server to know if the session/token is expired, which requires an internet connection, it may happen that the user can turn off the internet connection and open the app running in the background and the app will not be able to determine if the session/token is valid.

TL;DR This article contains the implementation of a flutter package called local_session_timeout. If you directly want to start using it, please visit [https://pub.dev/packages/local_session_timeout](https://pub.dev/packages/local_session_timeout)

Let’s create a widget, that will redirect users to the login page regardless of whether it’s an online or offline application.

**Requirements:**
1. We need a stateful widget that listens to the application lifecycle state, i.e., if it is active, inactive, paused, or resumed.
2. We need to expose a stream to emit timeout events.
3. We want the duration of the timeout to be passed as input, instead of hardcoding.
4. We need to widgets that can listen to user interactions — Listener, GestureDetector, InkWell,...

_**We need a stateful widget that listens to the application lifecycle state**_


{% gist 
https://gist.github.com/SankethBK/a09a328ed3640fd68c0702b7e4a40944 %}

We are using two Timer objects, one for _userInactivityTimeout_ and another for _appLostFocusTimeout_. To listen to AppLifeCycleState we have to use WidgetsBindingObserver mixin.

**_We need to expose a stream to emit timeout events_**

We need to create another class, which holds all the configurations of timeout — like the duration of each timeout, exposing stream.

{% gist https://gist.github.com/SankethBK/6e065fb6c7f635602ac7e286c45f7eaf %}

**_We want the duration of the timeout to be passed as input, instead of hardcoding_**

Let’s pass out the _SessionConfig_ object as dependency injection to _SessionTimeoutManager_ widget that we created earlier. Now we can add Timer when AppLifeCycleState is inactive or paused. We need to cancel the Timer if the user re-opens the app running in the background before the timer expires.

{% gist https://gist.github.com/SankethBK/1c300c565e35902cee96dc7b0b2a013f %}

We have completed the timeout part, when the app loses its focus and gets pushed to the background, let’s do the same for user inactivity.

We will use the [Listener](https://api.flutter.dev/flutter/widgets/Listener-class.html) widget to listen to pointer events. We are not using the famous [GestureDetector](https://api.flutter.dev/flutter/widgets/GestureDetector-class.html) because the pointer-events in GestureDetector are more specific, for eg: onTap will be called only after tap down and tap up events, if the user holds the tap for a while and then releases, onTap will not be triggered. But in Listener, onPointerDown will be triggered for all of the gestures like scrolling, dragging, etc.

{% gist https://gist.github.com/SankethBK/30a836311442698f2c62be529de75b79 %}

This completes the implementation. But there is an improvement — We are creating a new Timer object for every user tap in Listener widget. Depending on the number of taps this could be CPU intensive. So instead of creating a new timer for every user tap, we can create timer in interval of let’s say 30 seconds. (This optimization has been implemented in the package published in [pub.dev](https://pub.dev/packages/local_session_timeout))

**_Usage:_**

{% gist https://gist.github.com/SankethBK/5644477765d24efcaf444ef559f9588b %}

For complete usage guide and documentation, please visit For complete usage guide and documentation, please visit [https://pub.dev/packages/local_session_timeout](https://pub.dev/packages/local_session_timeout)

Source code: [https://github.com/SankethBK/local_session_timeout](https://github.com/SankethBK/local_session_timeout)
Thank you!