Steps to secure your Flutter Application
Protection for snapshots / Screen Recordings
To protect sensitive data, block the user to take the snapshot or screen recording of the critical or sensitive information
For a particular screen,
await FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE);
To secure the complete app,
For Android :
Import the given file in the android manifest file
import android.view.WindowManager.LayoutParams;
and this line in the onCreate method,
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
// add this line
getWindow().addFlags(LayoutParams.FLAG_SECURE);
}
For IOS :
add this line in the AppDelegate.m class,
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self]; return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (void)applicationWillResignActive:(UIApplication *)application{ self.window.hidden = YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application{ self.window.hidden = NO;
} @end
You can read more about the package on the pub.dev using the link given below
Secure Storage
The shared preferences plugin’s Readme page in pub.dev states that there is no assurance that the data being stored on storage is secure.
Since, shared preferences data is not secured that may lead to expose sensitive information of the user.
To secure data data we can use,
Flutter Secure Storage Package,
It uses AES Encryption
for storing the data in android device and Keychain
for IOS Devices.
Hive Package,
It is very complicated to store the larger data and nested json in the flutter_secure_storage
To avoid this issue we can use hive database, which can store the larger data easily and effectively in the secured storage.
Keep current with the latest Flutter SDK releases.
The Flutter version must be updated, and these updates may address security flaws discovered in previous versions. Check the Flutter change log for security-related updates.
Code Obfuscation
The technique of altering an app’s binary to make it more difficult for humans to understand is called code obfuscation. Your app’s API keys, classes, and all of your keys may be made public by reverse engineering. Your business logic may depend on this information, and the attacker could use it to access private user information. It is challenging for an attacker to reverse engineer your exclusive software since obfuscation conceals these in your produced Dart code.
Obfuscating applications is quite simple with Flutter. Build a release version of your application using the --obfuscate
and --split-debug-info
flags to obfuscate it.
flutter build apk --obfuscate --split-debug-info=/<project-name>/<directory>
Rooting or Jailbreaking protection
The manufacturer-imposed restrictions on the user can be removed by rooting Android devices or jailbreaking iOS devices. As a result, malware that affects your application or its data may be introduced. You might wish to notice this in such a situation and act accordingly. You might therefore wish to check whether the device is rooted or not.
To detect the root for and android device or jailbreaking on IOS device, Please see the package given below.
For Developer Mode (Android only)
bool developerMode = await FlutterJailbreakDetection.developerMode;
For Production,
bool jailbroken = await FlutterJailbreakDetection.jailbroken;
Handshake Validation
For some enterprise apps, we only need to connect to the domain server. Therefore, we must include the code that verifies the host’s identity and the host server’s IP Address in order to achieve that.
import 'package:dio/dio.dart';void main(){
HttpOverrides.global = new MyHttpOverrides();
runApp(MyApp());
}class MyHttpOverrides extends HttpOverrides{const HOST_IP_Address = your_ip_address;
@override
HttpClient createHttpClient(SecurityContext context){
return super.createHttpClient(context)
..badCertificateCallback = ((X509Certificate cert, String host, int port) {
final isValidHost = [HOST_IP_Address].contains(host); // <-- allow only hosts in array
return isValidHost;
});
}
}void getHttp() async {
Dio dio = new Dio();
Response response;
response = await dio.get(HOST_IP_Address);
print(response.data);
}
NOTE : Just change your_ip_address
to your specific domain IP Address.