Whether you are developing a traditional native app, a cross-compiled app from the likes of Appcelerator or Xamarin, a hybrid app with Ionic, or a JavaScript-native app with NativeScript or React Native, a common thread that runs through each is app security.
More than ever before, I think we developers are far more aware of the myriad security issues we face. When you develop a cross-platform mobile app with NativeScript, you are developing a truly native app. But that also means the same security considerations apply as with any other native mobile app.
Watch the webinar Best Practices for Securing Your Mobile Apps to get some tips and tricks on NativeScript security!
In the previous article, we dove into securing our source code via advanced obfuscation, preventing code tampering, reducing the scope of our installations, and migrating sensitive business logic to the cloud.
Today our focus in on how we store (and secure) data locally. So let's get to it!
- Part One: Protecting Your Source Code
- Part Two: Securing Data at Rest (that's today!)
- Part Three: Ensuring Data Integrity Between Device and Server
- Part Four: Enterprise User Authentication and Authorization
Check out the new course from NativeScripting.com on mobile app security and get 30% off with the code: NSSECURE.
Encrypt Local Data
Out of the box both iOS and Android prevent data stored by one app to be accessed by any other app on the system. However, as we all know the road to hell is paved with good intentions, amirite? 🔥😰
So it's always best to encrypt any and all data we are saving to the device.
Luckily for us, the nativescript-secure-storage plugin exists!
The Secure Storage plugin allows us to encrypt, save, decrypt, and retrieve key/value pairs:
// require the plugin
import { SecureStorage } from "nativescript-secure-storage";
// instantiate the plugin
let secureStorage = new SecureStorage();
// async
secureStorage.set({
key: "foo",
value: "I was set at " + new Date()
}).then(success => console.log("Successfully set a value? " + success));
// sync
const success = secureStorage.setSync({
key: "foo",
value: "I was set at " + new Date()
});
NOTE: Internally, on iOS this plugin uses KeyChain via the SAMKeychain library and Android via the Hawk library (which in turn uses Facebook conceal).
Encryption with SQLite + SQLCipher
Are you a fan of SQLite? Did you know there is a full-featured NativeScript plugin that supports SQLite? Well now you do!
The free version (above) of the SQLite plugin provides all of the capabilities you've come to expect from SQLite. However, there is a paid option that also includes encrypting your SQLite database at rest. By leveraging SQLCipher, you can have transparent 256-bit AES encryption of your SQLite database on your user devices.
Online/Offline Data Sync + Encryption
Many of us use mobile backend services (mBaaS) like Firebase or Progress Kinvey for our remote backends. And when developing mobile apps, we need to be aware of online/offline connectivity, and syncing up data for when users toggle between those states (lest the app crashes without a network connection!).
Out of the box, Kinvey comes with online/offline data sync baked in, as outlined in this extensive code sample example from the docs:
// Retrieve an instance
const dataStore = Kinvey.DataStore.collection('books', Kinvey.DataStoreType.Sync) as Kinvey.SyncStore;
// Pull data from the backend and save it locally on the device.
const promise = dataStore.pull()
.then((entities: Array<{}>) => {
// ...
})
.catch((error: Kinvey.BaseError) => {
// ...
});
// Find data locally on the device.
const subscription = dataStore.find()
.subscribe((data: Array<{}>) => {
// Called once, with local data
}, (error: Kinvey.BaseError) => {
// ...
}, () => {
// Called after the local data has been retrieved
});
// Save an entity locally to the device. This will add the item to the sync table to be pushed to the backend at a later time.
const entity = {};
const promise = dataStore.save(entity)
.then((entity: {}) => {
// ...
})
.catch((error: Kinvey.BaseError) => {
// ...
});
// Syncs this store with the backend. This will first push any pending changes on the device to the backend and then pull data from the backend onto the device.
const promise = dataStore.sync()
.then((entities: Array<{}>) => {
// result will contain the results of the push to the backend and a pull from the backend
// result = {
// push: [], // pushed entities
// pull: [] // pulled entities
// };
//
// Each item in the array of pushed entities will look like the following
// { _id: '<entity id before push>', entity: <entity after push> }
// It could also possibly have an error property if the push failed.
// { _id: '<entity id before push>', entity: <entity after push>, error: <reason push failed> }
})
.catch((error: Kinvey.BaseError) => {
// ...
});
Additionally, Kinvey provides for encryption of the data at rest on the device, using SQLite and SQLCipher, which is simply configured automatically when you initialize Kinvey:
Kinvey.init({
appKey: '<appKey>',
appSecret: '<appSecret>',
encryptionKey: '<encryptionKey>'
});
Backend Compliance and Security Considerations
Many of us who develop apps in the enterprise are acutely aware of compliance and security regulations. Here in the US, a big one for developers creating apps for health care providers or insurance companies is HIPAA.
If you are developing an app that deals with PHI (private health information) in the health care industry, you absolutely need to make sure the data storage and transmission of said data is HIPAA-compliant.
Kinvey reviews, affirms, and evolves security controls on an annual basis via SOC2, HIPAA, GDPR, Sarbanes-Oxley, and other compliance activities. For customers in banking focused on FFIEC or GLBA regulations, in health care focused on HIPAA, or doing business in the EU and concerned about GDPR, the Kinvey platform provides comprehensive end-to-end security with the capabilities needed to support your regulatory compliance efforts.
Read more here about how Kinvey can provide your organization the security and compliance coverage it requires.
Next Up is Episode Three: Securing Data in Transit!
Today we covered storing private data elements securely in our app and even looked into some local and remote secure data storage options. Next up we are going to look into how we securely transfer data back and forth from the client to the server. Hint: it's not quite as simple as SSL. 🤔
Top comments (0)