Learn how to securely store tokens and API keys in Flutter apps using best practices, libraries, and expert recommendations with code samples.
📌 Table of Contents
-
Introduction
-
Why Secure Storage Matters in Flutter
-
Understanding the Risks of Insecure Storage
-
Expert Views and Industry Standards
-
Recommended Libraries for Secure Storage in Flutter
-
Step-by-Step Tutorial Using
flutter_secure_storage
-
Handling Sensitive Data in Production
-
Common Mistakes and How to Avoid Them
-
Token Refresh Strategy and Expiry Handling
-
Practical Problem Solved
-
Summary
-
Final Thoughts
-
Disclaimer
🛡️ Introduction
In today’s digital world, mobile apps frequently interact with servers, APIs, and databases. To authenticate these interactions, tokens and API keys are used. However, storing these sensitive credentials insecurely can expose your app to attacks, reverse engineering, and data breaches.
In this blog post, we’ll explore how to securely store tokens and API keys in Flutter, use trusted libraries, follow best practices, and walk through a complete Flutter secure storage example.
🔐 Why Secure Storage Matters in Flutter
APIs are gatekeepers to powerful services such as Firebase, Stripe, and your custom backend. If someone accesses your API key or token:
-
They can impersonate users.
-
Abuse your API rate limits.
-
Cause data leaks or even financial loss.
-
Damage your brand's credibility and trust.
⚠️ Understanding the Risks of Insecure Storage
Here’s what can go wrong when API keys or tokens are stored insecurely:
-
Storing tokens in SharedPreferences (which are plaintext).
-
Embedding API keys in source code.
-
Lack of obfuscation or encryption.
-
Not rotating or expiring tokens..
— OWASP Mobile Top 10 Report
🧠 Expert Views and Industry Standards
According to OWASP and Google’s Android security guidelines:
-
Always use encrypted local storage for sensitive data.
-
Prefer hardware-backed keystore or Keychain on iOS.
-
Avoid hardcoding secrets.
Flutter experts like Reso Coder and the team at Very Good Ventures recommend using packages like flutter_secure_storage
or platform channels to access secure system storage.
📚 Recommended Libraries for Secure Storage in Flutter
Here are trusted libraries used for secure data storage:
Library | Description | Platform Support |
---|---|---|
flutter_secure_storage |
Stores data securely using Keychain/Keystore | Android, iOS, macOS |
secure_storage |
Advanced with AES encryption | Community-maintained |
encrypt + path_provider |
Manual secure file encryption | Cross-platform |
flutter_secure_storage
Let’s implement secure token storage using the flutter_secure_storage
package.
🔧 Step 1: Add Dependency
In pubspec.yaml
:
dependencies:
flutter_secure_storage: ^9.0.0
Then run:
flutter pub get
🧪 Step 2: Import the Package
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
🏗️ Step 3: Initialise Storage
final storage = FlutterSecureStorage();
✍️ Step 4: Write Token to Secure Storage
await storage.write(key: 'auth_token', value: 'your_jwt_token_here');
📖 Step 5: Read Token
String? token = await storage.read(key: 'auth_token');
❌ Step 6: Delete Token
await storage.delete(key: 'auth_token');
🔄 Optional: Delete All Data
await storage.deleteAll();
📌 Note: On Android, it uses EncryptedSharedPreferences. On iOS, it uses Keychain.
🧩 Handling Sensitive Data in Production
For production-ready security, consider:
-
Obfuscating build:
flutter build apk --obfuscate --split-debug-info=/<output-dir>
-
Disabling screenshots on sensitive screens.
-
Secure networking (HTTPS, cert pinning).
-
Code minification and symbol obfuscation.
🚫 Common Mistakes and How to Avoid Them
Mistake | Why It’s Dangerous | Recommended Fix |
---|---|---|
Storing tokens in plain SharedPreferences | Easily accessible | Use flutter_secure_storage |
Hardcoding API keys | Extractable from APK | Use secure storage or environment variables |
Not deleting tokens on logout | Session hijacking risk | Always delete() on logout |
🔄 Token Refresh Strategy and Expiry Handling
🎯 Tip: Store Expiry Metadata
await storage.write(key: 'token_expiry', value: expiryDate.toIso8601String());
🧠 Tip: Refresh on Launch if Expired
DateTime expiry = DateTime.parse(await storage.read(key: 'token_expiry') ?? '');
if (DateTime.now().isAfter(expiry)) {
refreshToken(); // Your logic
}
“Rotating tokens and setting expiration reduces the blast radius of token misuse.”
— Auth0 Security Guide
✅ Practical Problem Solved
Problem: A developer hardcoded an API key in the Flutter app and it was exposed in GitHub. Within 24 hours, it was abused for 3000 requests causing a spike in billing.
Solution:
-
Moved key to server.
-
App now authenticates via OAuth.
-
Tokens stored securely using
flutter_secure_storage
.
💡 Moral: Always treat API keys and tokens like passwords.
📝 Summary
-
Use
flutter_secure_storage
to store tokens securely. -
Avoid hardcoding or storing in plain preferences.
-
Handle token lifecycle smartly.
-
Always test secure storage handling in production builds.
-
Regularly audit your code for secret leakage.
💬 Final Thoughts
Security is not a one-time task—it’s an evolving discipline. As Flutter developers, our responsibility extends beyond UI and performance. Protecting user data and securing access to APIs is critical for building trustworthy mobile apps.
⚠️ Disclaimer
Disclaimer:
While I am not a professional Flutter developer or UI/UX expert, I have
thoroughly researched this topic using official Flutter documentation, expert
opinions, and industry best practices to compile this guide. This post aims to
provide helpful insights and practical examples to support your learning
journey. However, for advanced or complex Flutter projects, seeking advice from
experienced developers is always recommended to ensure best results.
Your suggestions and views on Flutter responsive design are welcome—please share below!
Previous Post 👉 Using GraphQL with Flutter: A Beginner’s Guide
Next Post 👉 Local Database Solutions in Flutter: Hive vs SQFLite