15 secure coding practices to use in digital identity

Secure coding of any application or service is important, but it is vital in systems that process personal data.

blue green abstract finger print identity bio security fingerprint
Getty Images

When software analysis firm CAST analyzed 1380 software applications they found a whopping 1.3 million software vulnerabilities in the code.

Anyone reading CSO will know that software flaws give cybercriminals an open door.

Identity management is arguably the most at risk service of all technology disciplines. Identity theft stalks us all. Javelin Research has reported on identity theft for a number of years now and their research shows that it continues to plague the industry. In its 2018 Identity Fraud report, advisory firm Javelin described 2017 statistics as being at a “record high.”

In identity management, we often talk about “weaponizing identity.” This means hardening the system across access points and where users interface with the service. However, the process to weaponize needs to be layered and one such layer is at the code level.

Secure coding for identity management

Digital identity platforms can be very complex, as they often have to rely on external data sources and integrate with third-party APIs. Consumer versions of identity and access management (IAM) can be even more complex. They may require extended functionality to upload, store and share documents and images. Many identity services also incorporate, or are entirely based on, mobile device apps. It is not enough to rely on the inherent security of the protocols that communicate across the components of an identity ecosystem. The underlying code must be as secure as possible without restricting the functionality of this ecosystem.

Here are some of the best secure coding practices to use when developing an identity platform.

1. Use good resources: Start with the secure coding 101 resource, Open Web Application Security Project (OWASP). OWASP is the de facto, go-to resource for secure coding. Their “Quick Reference Guide” for secure coding is a great place to start and to use as a double-check tool during development. Use their resources liberally.

2. Use defensive programming techniques. This helps to avoid exploitable bugs. An example is in equivalence comparisons: put the constant first. This will trigger an error at compile or run-time if you accidentally write equals in place of the equality operator. For example:

// poor practice:
if ($result == 'SUCCESS') {
// better - if “==” mistyped as “=” get runtime or compile error
 if ('SUCCESS' == $result) {

3. Sanitize data: Digital identity, especially systems for consumers, will often call out to external data sources. All data from external sources or that supplied by a user should be untrusted. For web clients this includes data obtained from query string or hash parameters, cookies, local storage, etc.; for server-side apps this includes data supplied via POST, GET, cookies, etc. Native apps often read configuration files, which may be deliberately tampered with.

In all cases, the first line of defense is sanitization:  check that only the permitted characters/format has been included. This includes ensuring that maximum data field lengths are checked to avoid buffer overflow attacks. 

Another area that is important to security check in a digital identity platform is image upload. Images are becoming more important in IAM and CIAM services as data stores increasingly store and share photos of identifying documents. User upload of files, such as images, can be particularly dangerous. These must be rigorously checked to ensure they really are images and don’t have hidden executable content.  

4. Screening: Document and other file storage is a major part of a digital identity ecosystem. All data to be placed in storage must be screened for executable content. This applies regardless of the underlying database technology. For example, although non-SQL databases are not vulnerable to SQL injection attacks, they do have their own vulnerabilities.

5. Filter: Similarly, never accept external command strings directly. Always pass through a filter to check if a command is valid and applicable within the context.

6. Prevent unverified code execution: Avoid the use of eval() type functions, as these permit execution of unverified code. This includes the use of functions that have eval() hidden, such as JavaScript’s SetTimer().

7. Resilience is king: Developing consumer-focused digital identity services often means that you need to cover a wide demographic. You need to allow for wide-ranging values. Try to code your application with resilience in mind so that, for example, it doesn’t fall over or permit code injection if external data values lie outside of expected ranges or values. Good unit or functional testing can often detect such problems.

8. Take care when using open sourcePermitting the use of the latest version of open source code in builds has resulted in inclusion of malware into products. When using open source packages, prevent the use of unverified versions by setting the specific version number in your package manager. Build processes should include a hash check of all external files.

9. Error responses: Error responses are a vital part of a digital identity service as they inform the user of issues and improve usability. However, they can be used by malicious entities to work out the behavior of a system. Ensure that these do not leak information to an attacker. Client-server error responses should include only a minimum of information to inform the user, and not assist an attacker.

10. Use audit logs: If an attack does occur, you’ll want to know what and how. However, be sensible with logging — filling up logs with pointless audit data can be counterproductive.

11. Digital signatures: Where possible, use digital signatures to verify data integrity. HMACs are cheap to compute and valuable for this purpose. Similarly, if data is at all sensitive, including personal data, this should be encrypted during transport and storage. Always use TLS for anything conveyed across public or private networks.

12. Tokens for secure communications. For inter-process communications, consider the use of tokens in place of password authentication.

13. Mobile apps: Mobile device apps are increasingly being used as a channel for digital identity proof and transactions. Assume the device can be jailbroken. Carefully examine the data that you are handling and evaluate the risks involved. Consider incorporating jailbreak detection code where possible.

14. Check for vulnerabilities: This should be done whenever a new upgrade or release is done. There are a number of specialist companies that can provide this service. Companies like CheckMarx or CAST offer an independent source code analyzer service. Such solutions are an important part of any secure coding practice, although they should not be thought of as a replacement for manual examination of code, rather an additional layer of checks.

15. Most important of all: Keep up to date with emerging vulnerabilities. Serious flaws are always popping up as CVE Details attests. It is important to be aware of new threats and act to ensure these are not present in your code.

Secure coding of any application or service is important, but it is vital in systems that process personal data. If you design or develop digital identity systems, security and usability will always be a hard balancing act. However, with good secure coding practices you can manage the threat of a cyber attack while ensuring the complex functionality of a consumer identity system is achievable.

Copyright © 2019 IDG Communications, Inc.

Get the best of CSO ... delivered. Sign up for our FREE email newsletters!