Nerd For Tech
Published in

Nerd For Tech

Mobile Banking: Security Practices

When you are developing any fintech application, security will be the essential thing you will have to take care of, especially when working on mobile banking apps. Users expect financial institutions’ responsibility because they often entrust them with everything they have. And to build that trust, it is essential to keep users’ data and money safe.

Of course, there are many security standards and audits the app needs to pass in the banking sector before it can be delivered to users. And it is better to be prepared for those kinds of tests. This article will focus on the main features that should be implemented or need to be kept in sight when creating a secure and safe banking application.


First of all, let’s divide security features into two groups (or layers) — local and remote. These groups can be isolated on their own layer in typical cases, but sometimes they will collide.

The local group contains features that depend only on front-end developers’ work. Those kinds of features prevent only local threats, mainly. Typically, these are the threats that could lead to the leaks of user’s data (or any sensitive information) from the device to third parties. Features to review are data and file encryption, cache strategy, and biometric security.

We put features that cover or eliminate client-server threats into the remote group. The main danger of these threats is the ability to disrupt or interfere with the client-server communication channel. This layer will review the problems with client-server protocols, certificates, authorization, and push notifications.

Data encryption algorithms

Let’s start with the local feature group and the data encryption issues. In our opinion, this is the most crucial feature you need. Modern applications store any user’s information, server metadata, sensitive files, and basic settings. And all this happens even if you build regular apps, but some applications also provide an offline mode and offline access to the latest user’s data. In this case, the amount of local data grows exponentially over time.

So the question here is, do you trust device storage and development tools? Because most of the time, the default tools you may use in everyday work do not take advantage of the latest security practices or aren’t safe at all. And the device storage may have the most unexpected security flaws.

For example, the default Android framework that allows you to work with a local database relies only on the fact that the database is stored in secure system storage, so there’s no need to encrypt its content. But for us, it is unacceptable. What if a hacker could access a user’s device and somehow gets root access or access to that secured folder with app files, or somehow access the database from memory directly? The simple solution is to encrypt the database and eliminate even a slight chance of attack. There are tools for that — not common among most developers, but they exist, and they’re straightforward to use.

Any encryption requires algorithms and keys. As for the algorithms, everything can be quite obvious. Mobile platforms usually have AES, RSA, SHA hash algorithms available from the box. Even MD5 hash still could be helpful in simple cases. We recommend getting acquainted with these algorithms. Let’s now move on to the encryption keys.

Encryption keys

Almost any encryption algorithm requires encryption keys. It could be a single key or pair of public/private keys. Fortunately, nearly all modern systems give us tools to generate such keys. In Android, for example, this tool is called Keystore API. It allows you to create several types of keys and even use them immediately with several different encryption algorithms. iOS also provides a similar API.


The most important feature here is that these keys can be stored in the device’s hardware if it has a separate encryption processor. Unfortunately, this advantage usually applies only to premium devices. Otherwise, the keys will be generated and stored on a software level but still with a high protection level. Anyway, we need these APIs. Although this couldn’t be blind trust, we can trust the operating system in this case.

When you use cross-platform solutions or develop some custom applications, you may not have direct access to systems APIs. In this case, you can search for third-party solutions or write custom interfaces to get access to the necessary platform tools. But you need to carefully study the instruments you are using because users’ data protection depends on the quality of those tools.

What to encrypt

Ok, so now we have the encryptions algorithms and keys. What do we need to encrypt? First of all, as mentioned earlier — local database. Second — the application preferences. Usually, they store some user or app settings, and we need to secure them. Sometimes developers save user tokens, IDs, or passwords in preferences files to get faster access to this information.

In Android, for example, the default API doesn’t provide any protection for such files. Except for when these files are stored in the private application folder where regular users do not have access. But when talking about intruder attacks, we are not considering regular users. So you have two options here — encrypt data by yourself or use secure application preferences with encryption.

The next feature in this chapter is the encryption of the content of remote requests. We might find ourselves in a situation where we can’t trust our communication channel with the server. It is more like a minor feature, but it underlines the importance of the local encryption algorithms and keys.

Let’s assume that we do not use requests encryption at the architecture level, but we need to get the user’s credit card pin code (or any other sensitive information) from the server. It would be irresponsible to ask the server to pass such information in a raw format. You can opt for using a one-time pair of public/private keys. The public key will be sent to the server; then, the server will encrypt the data. When we get our data back, we will decrypt it with a private key. Mission accomplished — user data was transferred safely.


The last item to discuss here is file security. Of course, you can store user files in a private app folder. The system will protect those files, but it does not give you 100% certainty. You may consider additional file protection. We already showed that encryption is pretty straightforward. It may slow down the app slightly, especially if the stored files are large. But at the same time, it adds to the app’s security level.

Here’s another tricky thing about files and data security in general. If you’re allowing other apps to access the user files and information, be careful about which agents you grant that access to. The common cases to consider are file-sharing and assistants (Siri, Alexa, Google, Cortana, etc.) integration features.

Encryption recap

The main point of the whole encryption chapter — use system keystores as a single source of truth and do not trust anything else, even the rest of the operating system (system storages, preferences files, etc.). The system protects the keys, and this protection is guaranteed by providers such as Apple, Google, etc. You can use various encryption tools because they are very similar, but the keys’ safety should be your top concern.

Okay, now let’s move to the next topics.

Сache strategy

By default, applications use many different cache strategies, but most of them are not secure out of the box. That’s why the next step here is to check your caching tools because they could expose all users’ data or, at the very least, simplify information extraction by a third party. Mostly, we are talking about data that the app receives from the server. If you suspect that users’ information is not secure enough or discovered a data leak due to caching errors, we can suggest two ways to fix the problem.

First, turn off the default cache entirely and use an encrypted database to store data. This approach is not straightforward and may increase your development estimates, but it has another benefit: you can access all the data offline and turn it into a useful feature. The second way is to add the encryption to the default caching system. This can be done on the architectural level and won’t cost much of your time.

Of course, there are always third-party libraries and frameworks that can help you, but we encourage you to check them before usage. Anyway, keep in mind that cache could be tricky and not always as secure as you would expect.

Application passcode and biometrics

We assume that almost every app has this feature now. Even your grocery list can be protected with a local passcode or biometrics. As for finance applications, this is the essential part of authorization flow.

Biometric protection is provided by the system-controlled API, and it is easy to implement, so why do we mention it in this article? The reason is, we want to concentrate primarily on the passcode functionality because it is the part you need to implement yourself. It could be a remote passcode stored on a server and working as a regular password in web applications. And we will discuss it in the following section.


You usually cannot use biometric authentication alone. You need a fallback if the biometrics can’t be used, or the device is broken, or for any other reason you can imagine. Most of the time, we use a local passcode to provide the primary and biometrics secondary auth methods. If you’re doing it too, we want to warn you — be careful where and how you store this passcode. The encryption will help you here.

Also, think carefully about the “Forgot passcode” feature because if the user can’t enter the code correctly, we should immediately fall into suspicion mode. When the user tries to recover his code, we could not let him do so without confirming that he is the actual client and not a hacker. The confirmation flow could be similar to authorization, but there is a lot to think about. In any case, it is better not to recover the user’s passcode at all but simply force him to create a new one after confirming his identity.

Client-server protocols

Let’s move to remote security features and issues. This would be more like a front-end view because you can write books about backend security and authorization practices.

Of course, the most important thing is the communication channel between the client and the server. Hopefully, we don’t need to say that SSL protection is essential. Let’s better talk about if this protection is enough for the bank application.


The answer is actually yes, and you will be completely fine with an HTTPS connection to pass most of the security audits. But maybe you should consider using encryption anyway. At least for the requests that could carry sensitive user information, like fetching credit card data, pin code, user documents, etc. We mentioned the example with pin code and one-time encryption earlier.

If you want to take your security to the next level, you can apply encryption to all client-server communications. And we will say that it will be fantastic. So why don’t banks always do it? Usually, the reason is that the complete encryption of all communications is a complicated task to do. Complicated means it’s expensive not only development-wise but also costly to support it. Besides, this would slow down the whole system and potentially over-complicate the authorization process.

But let’s say you decide to use SSL. Is it possible to somehow minimize threats without using encryption? Definitely — yes, and we can show you a couple of ways to reduce the probability of successful man-in-the-middle attacks.

Certificates protection

The SSL connection uses certificates that are nothing more than a pair of public/private keys given to you by certification authorities (CA). Before starting to talk to each other, the client and server perform handshaking, including a key and certificates exchange. This technology is a robust way of transmitting secret data without caring who sees your content. But as we mentioned before, it could be compromised, and here is how we can secure ourselves in 5 minutes.

The feature we are talking about is SSL pinning. Backend developers provide a hash of the certificate on the server and front-end developers hardcode it to the device’s HTTP client. Now, when the server or someone else tries to connect to the application, we calculate a hash of the certificate provided on the handshake and compare it with the client’s hash. If they match, we are sure that this is our server, and we can trust this connection. Otherwise, we will reject attempts to communicate with the device. Even if someone extracts the hash of the server certificate from the device or application build (in fact, it is easy to do), it won’t help. It is useless for the third party and almost impossible to reverse engineer.

SSL pinning is common practice in finance applications and the whole industry. Next, we want to talk about a less obvious thing — a client certificate.


A client certificate works the same way as a regular server certificate, except it’s stored on the client-side. In this schema, the server checks the authenticity of the connection. Using this technique and SSL pinning, we will have two side verification. It seems like another 5 minutes feature, but unfortunately, it is not.

The core problem here is that we can’t store client certificates in the app itself because the application package file could be easily reverse-engineered. If anyone could lay hands on the certificate so quickly, it is comparable to not using it at all. But there could be secure ways to deliver the client certificates to the device from the server or any other trusted source.

If we are talking about the server, we need to establish a trusted, secure connection. For this purpose, we can use advanced encryptions and key exchange algorithms. Some verification mechanisms are required to ensure that the server talks to the actual client. When the device receives the certificate, it could be saved into secured storage and encrypted.

There’s a lot of work to integrate a client certificate into the application. Is it worth it? Unfortunately, we can’t give you a universal answer here. The client certificate does not protect the client itself; it protects the server from unwanted connections outside of the bank infrastructure. But if you are confident that your server is secure enough, you may decide not to spend your resources on a feature such as a client certificate.


It is the last big topic for us. The authorization in mobile banking is rarely different from the other applications. Usually, it’s the same JWT tokens scheme that is common in software development. Here we want to discuss the two most important authentication methods for financial applications — passcode and biometric authentication. We mentioned earlier in the local section that you can also use them remotely when you want to control all authorization from the server.


The problem we face is the authorization tokens updating. When the user logs in to the application after entering the correct passcode or after using biometrics, he should be able to retrieve new tokens from the server to use the app.

The access token has a short time-to-live (TTL), so usually, in this process, you rely on a refresh token, whose TTL is much longer. But the problem is that the TTL of the refresh token couldn’t be too long, either. It is still longer than the access token but shorter than it takes to renew a user session; usually, it lives no more than 30 minutes. The refresh token, which is set to be available for a couple of weeks or months, is dangerous for the system and could be classified as a security threat source.

In the first case, when we have a long-living token, we can use local authentication and then simply update tokens on the first request the user performs. But if we choose secure short-lived tokens, we need to update tokens manually. To do so, we need to send a request to update tokens right after the user enters a passcode or goes through biometric authentication.

We cannot renew tokens if there is nothing to prove that we are a valid client. The first solution you can end up with is to use the hash of the passcode as an authorization factor, and later it will serve you more like a regular password. And this could’ve been a good solution because a pair of the old refresh token and the passcode are already a lot to compromise or steal. But we advise you first to create a reliable communication channel between the client and the server. Use a one-time encryption key for that. This approach gives you more security and does not cost very much except for a couple of kilobytes of user traffic.

This schema works for not only passcodes but also biometrics. Biometric authentication is your second authentication method, so you should have a passcode anyway. You can store it (encrypted, of course) on the device and use it to update tokens after successful fingerprint scanning or Face ID recognition.

Below, you can see a schema from the official Google guide on implementing user verification after biometric authentication. It uses only a pair of asymmetric keys to establish a connection and perform token updating, but we think that you should use additional verification on top of it.


The passcode could be a good solution, but only if you trust the storage where you keep it; otherwise, it shouldn’t be stored on the device at all. But if you follow all the advice above and use good encryption mechanics, you should be able to store the user’s passcode securely.

Push Notifications

At the end of the remote security features section, we’d like to mention this little thing. Push notifications are a handy and fun feature; almost every app uses them nowadays. But it could be dangerous and tricky for mobile banking. Why? Because the data in notifications is open and not protected. It is not easy to fetch, but it is seizable for professional hackers. We couldn’t rely on the system or push notification providers to secure the information inside.

What can we do about it? The easy way is not to pass any sensitive information in notifications. For example, if you want to send a full transaction model in the push message to save it to the local database for further use, it is not a wise idea. It is better to send an ID of the transaction, and then the application could start a background service, establish a reliable connection to the server, and fetch the necessary information. Of course, you need to show something to the user; for this purpose, use as little data as you could.


The other two options are to use encryption. Yes, it seems to be a universal solution for everything, but it is not, believe us. Why two options? Because there are already push notification services (providers) that can provide you a good security level for notifications. Usually, they use encryption, so you don’t need to bother yourself and spend extra time.


We have tried to show you the main security issues and features you will have to consider if you want to create a safe and secure banking application. There are usually many more problems than described in this article. The solutions for security issues are not universal; each needs its unique approach. And you must decide which one to use, depending on the project’s situation and the level of safety you want to achieve. But it’s best to know what you can face.

As we mentioned earlier, almost all banking applications, primarily if they work with cards and payment operations directly, must go through several approvals and audits. These audits will help you find security breaches and issues and advise you on patching or eliminating them. There are also separate companies that do security audits; you can hire them if you need help.

Another thing that could be helpful is OWASP. It is a set of methodologies, documentation, and web application security tools. Even though these documents and practices mainly concern web applications, mobile developers can also find many valuable things there. It is worth your attention if you are trying to improve your security skills.

In conclusion, we want to say that users expect the safety of their information from their favorite apps. The developers are the ones who can ensure it. Take this task seriously to keep your users happy and your app stronger than physical bank vaults.

— — —
Alexander Kalnoy
Lead Android Developer at



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alty Inc.

Alty Inc.

We create custom functional applications for big companies.