I have been working on flutter for more than 2 years and I have seen many flutter developers who are not aware of the security issues in a flutter. So I have decided to write this article to make flutter developers aware of the security issues in flutter and how can you make your application secure so let's start.
Securing API Keys
API stands for "Application Programming Interface". An API is a set of rules, protocols, and tools that define how software components should interact with each other. In other words, it is a way for different software applications to communicate and exchange information with each other.
we can secure API hard-coded either in dart or Native(Android, iOS, web)
- API keys in Flutter code
for example, I have to use the API key in Dart code
void main(){
String API_KEY="********"; //bad practice
}
for avoiding this, we can use String.fromEnvironment() or .env
file.
String.fromEnvironment()
implementation
- Load API in Dart code ```
void main(){
String? apiKey = String.fromEnvironment('API_KEY', defaultValue: null); //get api key from environment
runApp(MyApp(apiKey: apiKey));
}
- While compiling code pass the API key as an environment variable
flutter build apk --dart-define==API_KEY=SECRET_KEY
## Load API key From `.env` file
for fetching API keys from the `.env` file use the following package:
[flutter_dotenv](https://pub.dev/packages/flutter_dotenv)
> Note Do not forget to add the `.env` file in the `.gitignore` file
## API keys in Native code
for example, Google Map API needs to be added to Android, iOS, and the web in respective files but APIs are not secured in `AndroidManifest.xml`, `info.plist`, and `index.html`.
[Adding Google Map to flutter](https://codelabs.developers.google.com/codelabs/google-maps-in-flutter#3)
## Android:
- Insert your API key in `local.properties `file
google.maps_api_key=SECRET_KEY
- Add local.properties file in `.gitignore` file
- Now read the API key from `local.properties` file in `build.gradle(app)` file.
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def googleMapsApiKey = localProperties.getProperty("google.maps_api_key")
android {
defaultConfig {
manifestPlaceholders = [
googleMapsApiKey: googleMapsApiKey
]
}
}
- and add it to your AndroidManifest.xml file
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${googleMapsApiKey}" />
## For iOS:
- Add your API key in `ios/Flutter/Release.xcconfig` file
GOOGLE_MAPS_API_KEY=$(SECRET_KEY)
- Same as debug.xcconfig file
- Now refer to these keys in `info.plist` file
google_maps_api_key
$(GOOGLE_MAPS_API_KEY)
- Now add it to your `AppDelegate.swift` file
GMSServices.provideAPIKey("$(GOOGLE_MAPS_API_KEY)")
# For the web:
it is a little bit complicated but you can refer to the following link:
[Dyanmic Html Elements- An approach to Flavours in Flutter Web ](https://medium.com/flutter-community/dynamic-html-elements-an-approach-to-flavors-in-flutter-web-6bff1a7d655a) by [gonpalma](https://twitter.com/gonpalma)
## Encrypt Information and Storage
Encryption is the process of converting plain text data into an encoded format to ensure the confidentiality, integrity, and security of the data. In Flutter, encryption is often used to secure sensitive data such as passwords, user credentials, and financial information in mobile applications.
Flutter provides built-in support for encryption through the `dart:crypto` library, which includes various cryptographic functions such as hashing, symmetric encryption, and asymmetric encryption.
![meme 2](https://images.squarespace-cdn.com/content/v1/5c9051237d0c9173e4e58a19/1614147238291-DA792M3SPZ60ZUDBWRHD/Encryption+meme.jpg?format=750w)
- Encryption local storage: Local storage is a place where we store the data locally on the device. So we should encrypt the data before storing it in the local storage. You can use the following packages to encrypt the data before storing it in the local storage.
- [flutter_secure_storage](https://pub.dev/packages/flutter_secure_storage)
- [sqflite](https://pub.dev/packages/sqflite)
- [file_cryptor](https://pub.dev/packages/file_cryptor)
- Encryption Information: Sensitive data such as user credentials, payment information, and personal information should be encrypted both in transit and at rest. Flutter has built-in support for encryption through packages like [crypto](https://pub.dev/packages/crypto) and [encrypt](https://pub.dev/packages/encrypt).
# Make Authentication Proof Your App
Authentication is the process of verifying the identity of a user. There are two types of authentication: client-side and server-side. Client-side authentication is done on the client side, and server-side authentication is done on the server side. Server-side authentication is more secure than client-side authentication. So we should use server-side authentication. You can use the following packages to implement server-side authentication as per your requirement.
- [firebase_auth](https://pub.dev/packages/firebase_auth)
- [oauth2](https://pub.dev/packages/oauth2)
- [jwt_decoder](https://pub.dev/packages/jwt_decoder)
As server-side authentication is more secure but it is not that local authentication is not secure. So we should use local authentication as well. For local authentication, you can use bio-metric, pins, or patterns.
![image 2](https://i.pinimg.com/736x/66/02/68/660268df52e603c798f1291f6b09110c.jpg)
local authentication is most used in banking applications or for any financial application.
## Network Calls:
Network communication should be secured using `HTTPS` and `SSL/TLS` protocols to prevent data interception and tampering and to ensure data integrity. You can use the following packages to make network calls.
- [dio](https://pub.dev/packages/dio)
- [http](https://pub.dev/packages/http)
> Note: try to ignore making network calls from a host starting with http:// and try to make network calls from a host starting with https://
## is the Device Secure?
Any Banking application or Financial Application needs to be installed only on a safe device.
How can you check if a device is **Rooted** or **Jail Breaked**
You can use the following packages to check if the device is rooted or not.
- [flutter_root_detection](https://pub.dev/packages/flutter_root_detection)
- [flutter_jailbreak_detection](https://pub.dev/packages/flutter_jailbreak_detection)
## Can your App could be Reverse engineered?
![image 1](https://i.stack.imgur.com/ZeBe6.png)
yeah, it is possible to reverse-engineer the source code. So we should obfuscate the source code. see here if you distribute debug build then it is easy to reverse-engineer the source code. So we should distribute the release build. But still, it is possible to reverse engineer the source code. So we should obfuscate the source code.
- [Decompile flutter app](https://stackoverflow.com/questions/53666487/flutter-debug-apk-decompile-to-get-the-source-code)
To obfuscate the source code you can use the following command
flutter build apk --obfuscate --split-debug-info=debug_info
read more about obfuscation [here](https://flutter.dev/docs/deployment/android#obfuscate)
# Control Background snapshots:
The following package [secure_application](https://pub.dev/packages/secure_application), Secures app content visibility when users leave the app. It will hide content in the app switcher and display a frost barrier above locked content when the user gets backs.
## Best Practices for Flutter App Development to make it more secure
- Avoid using third-party libraries: As we know flutter has a lot of packages to make our work easy but we should avoid using third-party libraries as much as possible. Because we don't know what is going on inside the package. So it is better to use only trusted packages.
before using any package we should check the package's popularity and the number of contributors. If the package has a lot of contributors and a lot of people are using it then it is safe to use it.
![example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xwg3meedc5djfwh1oq61.png)
- Overloading Permissions: overloading permissions is a technique to ask for more permissions than required. For example, if you want to access the camera then you should ask for camera permission only. But if you ask for storage permission also then it is called overloading permissions. So we should avoid overloading permissions as much as possible because it is a bad practice and users will not like it.
- Avoid global variables or methods: for example, if you want to load a token from local storage then you should not store it in a global variable. Because if you store it in a global variable then it is easy to access it from anywhere. So it is better to store it in a local variable.
- Perform security testing: Regularly perform security testing to identify potential vulnerabilities and ensure that security measures are effective. This can include penetration testing, code reviews, and vulnerability scanning.
- Add Bug Bounty Program: A bug bounty program is a way to encourage ethical hackers to find and report vulnerabilities in your application. This can be a great way to find vulnerabilities that you may have missed. You can also offer a reward for finding vulnerabilities. This can help you find vulnerabilities before they are exploited by malicious hackers.
- Use a Secure Coding Standard: A secure coding standard is a set of rules that developers must follow when writing code. This can help ensure that developers are writing secure code and that vulnerabilities are not introduced into the codebase. You can use a secure coding standard to ensure that developers are following best practices and that vulnerabilities are not introduced into the codebase.
- For Production release use Pipeline: For production release use pipeline. The pipeline is a set of steps that are performed to build and release the application. This can include building the application, running tests, and deploying the application. This can help ensure that the application is secure and that vulnerabilities are not introduced into the application.
Pipeline tools example GitHub actions, bitrise, circleci, Jenkins, etc.
GitHub action to build flutter app and distribute to using firebase app distribution read [here](https://dev.to/djsmk123/flutter-firebase-app-distribution-using-github-actions-1fbo).
If I forgot anything you can add it in the comment section, will add it later.
![meme 3](https://i.pinimg.com/736x/40/d7/24/40d7243dcec513224602860a72ff6b90--done-meme-friday-memes.jpg)
> Follow me:
- [GitHub](https://github.com//djsmk123)
- [LinkedIn](https://www.linkedin.com/in/md-mobin-bb928820b)
- [Twitter](https://twitter.com/smk_winner)
Top comments (4)
i will be honest, this is absolutely a good article
Thankyou
π