Well, security should be no different. To build secure mobile apps, there are certain things that we're just going to have to do, and darn near every single time we write code.
So, what security goodies are in your bag of tricks? Here's some food for thought on some things you might find useful, in no particular order:
- Protecting secrets at rest --
Inevitably, we need to protect some data locally on the mobile device. Of course, the principles of sound design should guide us to minimize the data we store locally on the device. Some argue that we shouldn't really store anything of value locally, but our users don't always share that view. So we need to protect data locally: usernames (a la remember me button), passwords (best avoided, but for some consumer grade apps, it's acceptable), session tokens, customer names, and on and on.
We need a reliable set of tools that help us protect things locally. Both iOS and Android give us some ability to do that, but for times when we cannot rely on the OS, we need more. SQLcipher is one such example. It's an open source extension of SQLite that does AES-256 using the venerable OpenSSL library, and it works on Android and iOS.
- Protecting secrets in transit --
Of course, any modern OS and app can do SSL encryption, but things aren't always that simple. Sometimes we want to more strongly verify the SSL certificates on both ends of the connection. Sometimes we want to encrypt data that doesn't play nicely with TCP connections, like Voice over IP data that is best suited for UDP.
- Server connections --
We often need to connect to different types of back-end services, and of course those connections need to be established securely. At a network layer, we can use SSL, like I've described above, but at a data layer, we also need to ensure our connection is strong. For example, if we're connecting to an SQL database of some sort, we need to ensure our SQL API is immutable, and not subject to SQL injection and such.
- Authentication --
We need strong mutual authentication among all of our application components, of course, but we also need to authenticate users and any other entities our app interacts with. We can use x.509 certificates in some cases. Other times we need to use simple username/password combinations. Either way, though, the authentication needs to be mutual and worthy of trust. We have to avoid mistakes like hard coding credentials into our code.
- Authorization --
Once a user or entity is identified and authenticated, we then need to ensure that it is able to get to all the data and resources it needs, of course. But we also need to ensure that it is not able to get to data and resources that it doesn't need -- that it's not authorized to access. That means we need to weave access control throughout our system, and it needs to be consistently applied across our architecture.
- Input validation --
All data entering our application, through whatever input source possible, needs to be validated. For example, if we're expecting a credit card number, then our code should validate that a credit card number has indeed been input, and nothing other than a credit card number. That's called input validation, and it's vital we get it right. Input validation problems lead to cross site scripting and a myriad of other security problems, after all. But there are many decisions to make, like where do we perform input validation? Our design time choices can have vast impacts on our application's ability to perform its given tasks securely.
- Output escaping --