Migration to Flutter Guide
Discover our battle-tested 21-step framework for a smooth and successful migration to Flutter!
Home
Glossary

Secure storage in Flutter

What is secure storage in Flutter?

Flutter secure storage is the standard solution for storing sensitive data such as authentication tokens, refresh tokens, API keys, or cryptographic secrets in Flutter applications. Unlike regular local storage, it relies on operating system–level security mechanisms instead of app-managed encryption.

On Android, secure storage integrates with the Android Keystore and encrypted persistence layers. On iOS and macOS, it uses the system Keychain. In both cases, encryption keys are managed by the OS and never exposed directly to the Flutter layer.

Because of this, Flutter secure storage is designed for small, sensitive key–value data, not for general application state or large payloads.

How flutter secure storage works

The most commonly used package is flutter_secure_storage. It provides an asynchronous key–value API while delegating encryption, key management, and persistence to the underlying platform.

A critical detail is that secure behavior depends on configuration. On Android in particular, the default constructor historically allowed fallback to older encryption mechanisms that are slower and less robust. Modern Flutter applications should explicitly opt into EncryptedSharedPreferences to ensure correct performance and security characteristics.

All secure storage operations are asynchronous, as they involve disk access and cryptographic operations handled by the OS.

Flutter secure storage example (production-ready)

A modern, recommended setup explicitly configures Android options and uses secure defaults across platforms.

import 'package:flutter_secure_storage/flutter_secure_storage.dart';

const secureStorage = FlutterSecureStorage(
  aOptions: AndroidOptions(
    encryptedSharedPreferences: true,
  ),
);
Future<String?> readToken() => await secureStorage.read(key: 'access_token');

Future<void> deleteToken() => secureStorage.delete(key: 'access_token');

Future<void> saveToken(String token) => secureStorage.write(
  key: 'access_token',
  value: token,
);

The encryptedSharedPreferences flag forces Android to use the modern, optimized implementation backed by EncryptedSharedPreferences instead of legacy RSA/AES-based storage. This avoids UI freezes during app startup and prevents performance regressions that were common on older devices and low-end phones.

Flutter secure storage vs SharedPreferences

This distinction is fundamental.

SharedPreferences:

  • Stores data in plain text or lightly obfuscated form.
  • Is intended for non-sensitive configuration.
  • Is fast and simple.
  • Must not be used for credentials.

Flutter secure storage:

  • Encrypts data using OS-backed mechanisms.
  • Protects data even if app storage is compromised.
  • Is slower by design.
  • Is appropriate for secrets and authentication material.

If leaking the data would compromise user accounts or backend systems, SharedPreferences is not an option.

Platform-specific considerations

Android behavior

On Android, uninstalling the application removes secure storage data. However, secure storage can interact poorly with cloud backups. If encrypted data is restored from Google Drive backup but encryption keys are not, the storage may become corrupted and unreadable.

A recommended practice is either:

  • Excluding secure storage from Android backup in AndroidManifest.xml.
  • Or defensively handling read failures and resetting corrupted entries.

This prevents crashes or undefined behavior after device restore.

iOS Keychain persistence

On iOS, Keychain data persists after app uninstall.

This means a user can:

  1. Uninstall the app.
  2. Reinstall it.
  3. And still have authentication tokens present in secure storage.

At the same time, the app’s internal state, caches, and preferences are reset. This often leads to inconsistent behavior, where the app thinks the user is logged in but required context is missing.

A common mitigation is clearing secure storage on first launch after install. This is typically implemented by:

  • Storing an isFirstRun flag in SharedPreferences.
  • Wiping secure storage if the flag is missing.

Ignoring this can lead to subtle, hard-to-reproduce bugs in production.

Best practices for Flutter secure storage

  • Store only data that truly needs protection: Tokens, secrets, and encryption material are valid candidates. UI state, cached responses, or feature flags are not.
  • Avoid reading from secure storage directly inside frequently rebuilt widgets: Load sensitive data once during app initialization and keep it in memory when needed.
  • Always explicitly delete sensitive values on logout: Leaving stale credentials behind is a common security flaw.
  • Treat secure storage as protection for data at rest only: Once loaded into memory, the data must still be handled carefully.

Common mistakes when using Flutter secure storage

  • Assuming secure storage is secure by default without proper configuration. On Android, failing to enable encryptedSharedPreferences can lead to poor performance and legacy behavior.
  • Using secure storage as a general-purpose database. This introduces unnecessary overhead and misuses platform APIs.
  • Overlooking iOS Keychain persistence across reinstalls, which can cause authentication bugs that appear only in edge cases.

Learn more

Four mobile phones with small icons

Lessons Learned After Making the First 10 Commercial Apps in Flutter

There is always exciting technology our team wants to try out. We challenged them and asked for proof on how Flutter can bring value to the client. We are sharing the insights after making the first 10 commercial apps within the last 24 months during which we’ve spent some 17.193,00 hours on Flutter projects.

Choosing Indentity and Access Management solution

What is Identity and Access Management (IAM)? Introduction

With the changing landscape of identity management, at LeanCode we faced the challenge of selecting a new identity management solution that would be our default for the coming years. We want to share with you the whole journey. Find out more about our approach to this task.

Flutter Add to App

Flutter Add to App - Overview and Challenges Based on Real-Life Case

Flutter has taken the mobile market by storm, but not everybody knows that you don’t always have to write a Flutter app from scratch. It can be integrated into your existing application piecemeal. Read more about the Flutter add to app feature.