What is Session Management in BLoC?
Session management in BLoC refers to handling user authentication state, tokens, and session lifecycle using the BLoC pattern. It involves storing authentication tokens securely, persisting the session across app restarts, managing token refresh, and providing a smooth login/logout experience. A well-implemented session management system ensures that users stay logged in until they explicitly log out or their session expires.
Why Use BLoC for Session Management?
- Centralized State – Authentication state is managed in one place, accessible anywhere in the app.
- Persistence – With
hydrated_bloc, session state survives app restarts. - Security – Tokens can be stored in secure storage (e.g.,
flutter_secure_storage) and accessed only via the bloc. - Predictable Flow – Events like
Login,Logout,RefreshTokenlead to clear state transitions. - Separation of Concerns – UI does not directly handle tokens or API calls.
Setting Up Dependencies
Add the necessary packages to your pubspec.yaml:
Defining Authentication State and Events
First, define the state that represents the authentication status. Use Equatable for value equality and prepare for JSON serialization if you plan to persist using hydrated_bloc.
Building a Hydrated Auth Bloc
The auth bloc will extend HydratedBloc to persist the session across app restarts. It will also use flutter_secure_storage to securely store tokens (though we can rely on the bloc's persisted state, we might also store tokens separately for API interceptor).
Setting Up the Bloc Provider and Initialization
Initialize HydratedBloc and provide the auth bloc to the widget tree. Also, start the app with AppStarted event.
Protecting Routes with BlocListener
Use BlocListener to listen to authentication state changes and redirect accordingly.
Token Refresh in API Interceptor
When using an HTTP client like Dio, you can add an interceptor that automatically refreshes the token when a 401 response is received. This interceptor can access the auth bloc or the secure storage to get the current tokens.
Best Practices
- Store tokens securely – Use
flutter_secure_storageon mobile, orshared_preferenceswith encryption on web. - Use
hydrated_blocfor session state – It automatically persists and restores the state across app launches. - Validate tokens on app start – Don't assume a persisted token is still valid; verify with a lightweight API call or check expiration.
- Implement token refresh gracefully – Use an interceptor to handle 401 responses and retry requests.
- Clear sensitive data on logout – Delete tokens from secure storage and reset bloc state.
- Separate authentication from other business logic – Keep the auth bloc focused only on authentication events.
- Use
Equatablefor state comparisons – Prevents unnecessary rebuilds. - Test offline scenarios – Ensure the app behaves correctly when no network is available during validation.
Common Mistakes
- ❌ Storing tokens in plain text – Use secure storage, never
SharedPreferencesfor sensitive data. - ❌ Not handling token expiration – Leads to failed requests and poor user experience.
- ❌ Calling
BlocProvider.of<AuthBloc>(context)inside build without checking existence – Might throw if not provided. - ❌ Forgetting to add
AppStartedevent – The app will not initialize the session correctly. - ❌ Using
HydratedBlocwithout initializing storage – Results in runtime errors. - ❌ Not handling concurrent refresh requests – Multiple 401 responses could trigger multiple refresh attempts; use a flag to prevent duplicate refreshes.
Conclusion
Session management with BLoC provides a robust and scalable way to handle authentication in Flutter apps. By combining hydrated_bloc for persistence, flutter_secure_storage for token security, and interceptors for automatic token refresh, you can create a seamless and secure user experience. This pattern keeps your code organized, testable, and maintainable.