📱Securing Flutter App: Best Practices and Techniques (Part 3)🛡️
This is Part #3 of Securing Flutter App, you can Check the Part #1 Article & Part #2 Article for the first 4 Measures to secure your flutter app
In this Article We’ll continue Adding Security Layers to our Flutter App by Adding 2 more security measures to our App.
In Part #1 we used Code Obfuscation & Enforcing HTTPS and SSL Certificate Pinning.
In Part #2 we used App Integrity and Runtime Environment Checks & Secure Data Storage and Caching.
In this Part We’ll talk about the following:
- Biometric Authentication (Face ID/Fingerprint)
- Preventing Screenshots and Screen Recording
So, Let’s Start…
1. Biometric Authentication (Face ID/Fingerprint)
Biometric authentication, such as Face ID and fingerprint scanning, offers a seamless and secure way for users to authenticate their identity in mobile apps. By leveraging these technologies, Flutter apps can enhance both security and user experience, allowing quick access to sensitive data without the need for traditional passwords. Biometrics provide an added layer of protection, ensuring that only authorized users can access specific app features, while reducing reliance on easily compromised credentials. This makes it a vital component in modern mobile security strategies.
Biometric Types:
A. Fingerprint Authentication
uses the distinct ridges and patterns of an individual’s fingerprints to verify their identity. It is a well-established biometric technology and is supported by most modern smartphones. Due to its reliability and ease of use, it has become a standard method for securing mobile applications and devices.
B. Face Recognition
leverages the unique facial features of users to authenticate them. Thanks to advancements in camera technology and algorithms, this method is gaining significant traction in mobile security, offering a touchless and seamless user experience.
Steps to Add Biometric Authentication to Your Flutter App:
- Add the Local Auth package to your
pubspec.yaml
:
dependencies:
local_auth: ^2.3.0
2. IOS Setup:
Add the following to the ios/Runner/Info.plist
file:
<key>NSFaceIDUsageDescription</key>
<string>Why is my app authenticating using face id?</string>
3. Android Setup:
- Update your project’s
AndroidManifest.xml
file to include theUSE_BIOMETRIC
permissions:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<manifest>
- Ensure your
minSdkVersion
inandroid/app/build.gradle
is set to 23 or higher:
android {
...
defaultConfig {
...
minSdkVersion 23
}
}
local_auth
requires the use of aFragmentActivity
instead of anActivity
. To update your application:
— If you are using FlutterActivity
directly, change it to FlutterFragmentActivity
in your AndroidManifest.xml
.
— If you are using a custom activity, update your MainActivity.kt
to inherit from FlutterFragmentActivity
.
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity: FlutterFragmentActivity() {
// ...
}
4. Implementing Biometric Auth Service
- Create a new Dart file (
auth_service_handler.dart
) and add the following code to handle both Fingerprint and Face Recognition authentication:
import 'package:local_auth/local_auth.dart';
import 'package:local_auth/error_codes.dart' as auth_error;
class AuthService {
final LocalAuthentication _localAuth = LocalAuthentication();
Future<bool> authenticateWithBiometrics() async {
bool isAuthenticated = false;
try {
isAuthenticated = await _localAuth.authenticate(
localizedReason: 'Please authenticate to access this feature',
options: const AuthenticationOptions(
useErrorDialogs: true,
stickyAuth: true,
),
);
} on PlatformException catch (e) {
if (e.code == auth_error.notEnrolled) {
// Add handling of no hardware here.
} else if (e.code == auth_error.lockedOut ||
e.code == auth_error.permanentlyLockedOut) {
// ...
} else {
// ...
}
}
return isAuthenticated;
}
}
- Handling Biometric Authentication Errors
if (e.code == auth_error.notEnrolled) {
/// Indicates the user has not enrolled any biometrics on the device.
} else if (e.code == auth_error.lockedOut ) {
/// Indicates the API is temporarily locked out due to too many attempts.
} else if (e.code == auth_error.passcodeNotSet {
/// Indicates that the user has not yet configured a passcode (iOS) or
/// PIN/pattern/password (Android) on the device.
} else if (e.code == auth_error.notAvailable {
/// Indicates the device does not have hardware support for biometrics.
}else if (e.code == auth_error.otherOperatingSystem {
/// Indicates the device operating system is unsupported.
}else if (e.code == auth_error.biometricOnlyNotSupported {
/// Indicates that the biometricOnly parameter can't be true on Windows
}else if (e.code == auth_error.permanentlyLockedOut{
/// Indicates the API is locked out more persistently than [lockedOut].
/// Strong authentication like PIN/Pattern/Password is required to unlock.
}
Well, Done đź‘Ź, we now have a biometric auth in our App to make our App more secure.
but remember, testing biometric authentication on emulators can be limited. It’s best to test on real devices to ensure full functionality. However, some emulators do support basic fingerprint authentication.
2. Preventing Screenshots and Screen Recording
Preventing screenshots and screen recording is a crucial aspect of securing sensitive information in mobile applications. Unauthorized capture of on-screen content can expose personal data, confidential documents, or other sensitive information to malicious actors. By disabling these functionalities, developers ensure that users cannot easily capture or share sensitive content, providing an additional layer of security. In Flutter, implementing such measures enhances the app’s privacy, safeguarding both the user’s information and the integrity of the application’s data. This approach is particularly important for apps handling financial, medical, or personal data.
To prevent screenshot and screen recording in Flutter, we can do the following
1. Use of Platform-Specific Implementations
A. Android Setup:
To prevent screenshots on Android, you can use platform channels to call native Android code from your Flutter app. Here’s how to do it:
- Step 1: Modify your Android project files to add the required code.
In your MainActivity.kt
add the following code:
import android.os.Bundle
import android.view.WindowManager
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// below line prevents the user from taking screenshot or record the screen
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
}
}
B. IOS Setup:
- Step 1: Open your iOS project.
- Step 2: In your AppDelegate file (usually named
AppDelegate.swift
), add the following code:
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
// Add the code to prevent screenshots
if let window = self.window {
window.isSecure = true
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Now our security measures for this part is done âś…
🛡️ This is Part 3 / 4 for Securing Flutter App🛡️
📱Securing Flutter App: Best Practices and Techniques:
Part #1: 📱Securing Flutter App: Best Practices and Techniques (Part 1)🛡️
Part #2: 📱Securing Flutter App: Best Practices and Techniques (Part 2)🛡️
Part #3: 📱Securing Flutter App: Best Practices and Techniques (Part 3)🛡️
Part #4: 📱Securing Flutter App: Best Practices and Techniques (Part 4)🛡️