|
| 1 | +# Securing a backend app |
| 2 | + |
| 3 | +So far, you've learned how to create server side applications and how to use databases to persist and manipulate the data using CRUD operations. All these features sound awesome, but as it stands currently, they come with a high vulnerability and security risk. |
| 4 | + |
| 5 | +In this module, we will go over how we secure our app and how to make sure that neither intended nor unintended security breaches happen. |
| 6 | + |
| 7 | +Follow me in the following journey to understand why we need security. |
| 8 | + |
| 9 | +## Wishlist inventory app |
| 10 | + |
| 11 | +You've created an amazing app to store a shopping wishlist for your users. You have endpoints that retrieve the list, add an item to the list, update an item in the list, and delete an item in the list. |
| 12 | + |
| 13 | +I liked the app and started using it to create 2 lists for the things that I love, computers and kitchenware, and started adding items to both. |
| 14 | + |
| 15 | +In your database, you have 2 tables that store these items as follows: |
| 16 | + |
| 17 | +### Table 1: lists |
| 18 | + |
| 19 | +| id | name | |
| 20 | +| --- | -------------- | |
| 21 | +| 1 | Computer Parts | |
| 22 | +| 2 | Kitchenware | |
| 23 | + |
| 24 | +### Table 2: items |
| 25 | + |
| 26 | +| id | name | list_id | url | price | bought | |
| 27 | +| --- | -------------------- | ------- | --------------------- | ----- | ------ | |
| 28 | +| 1 | NVidia RTX 3070 | 1 | https://amzn.com/313 | $785 | false | |
| 29 | +| 2 | Philips Blender | 2 | https://url.com/313 | $90 | false | |
| 30 | +| 3 | AMD Ryzen 9 | 1 | https://amzn.com/585 | $599 | true | |
| 31 | +| 4 | Tefal Iceforce knife | 2 | https://amzn.com/1311 | $20 | false | |
| 32 | + |
| 33 | +Now, suppose another user comes to your app: how will your app decide what to show them? When they land on the homepage, they would see my items because the code can't decide what to show. This is the first security risk. The app needs somehow to relate the data to a specific user, so it only queries data that belongs to the requesting user. |
| 34 | + |
| 35 | +That's why almost everywhere online, you need to register or log in to an account in order to use an application, so the data can be related to you and you only. |
| 36 | + |
| 37 | +## Let's add some authentication |
| 38 | + |
| 39 | +To secure our wishlist above, we can add a new column to the lists table to attach it to an identity (a user). We can name that column `user_email` for example, and use this query to get the user wishlist: |
| 40 | + |
| 41 | +```SQL |
| 42 | +SELECT `id`, `name`, `user_email` from `lists` |
| 43 | +INNER JOIN `items` |
| 44 | +ON `items`.`list_id` = `lists`.`id` |
| 45 | +WHERE `lists`. `user_email` = "[email protected]" |
| 46 | +``` |
| 47 | + |
| 48 | +Thus, when a user comes to your app, you can ask them first about their email address, and then query the database to get their lists. But that is also insufficient. A malicious user can peep on other users' wishlists if he/she knew their emails, or he/she check different email combinations to see if it lands a hit, aka, **brute force**. |
| 49 | + |
| 50 | +To make this a bit harder to brute force, you can create a token system. Tokens are random strings of characters, usually with arbitrary length, that are intended to be hard to brute force (guess). A token can look something like this: `4f57ec27561d4524e6b5bb1f08fb7cccfb36a5e5` and is generated using special functions called _Cryptographically Secure Pseudo-Random Number Generator_ (CSPRNG). For example, you can run this code inside NodeJS to get a secure token using the `crypto` NodeJS library: |
| 51 | + |
| 52 | +```js |
| 53 | +const crypto = require("crypto"); |
| 54 | +const size = 20; // bytes (or 40 hex digits) |
| 55 | + |
| 56 | +const token = crypto.randomBytes(size).toString("hex"); |
| 57 | +console.log(token); // example output: 5d4225087676cf60670144e37b1694355a2e24d2 |
| 58 | +``` |
| 59 | + |
| 60 | +You can change the column `user_email` to `token` and every time a user comes in, you can ask them for the token, or allow them to generate a token. If they are new users, they can generate a new token, and save it, then start creating their lists. When they visit again, they enter that token to get their lists back. |
| 61 | + |
| 62 | + |
| 63 | + |
| 64 | +Bingo! You've just created your first, very adequate authentication layer! You've secured your app and **slimmed the chances** of brute-forcing user data! Many apps today use this pattern to secure data. However, keep in mind that you usually need other features to track, like user email, name, age, etc. So such a simplistic approach wouldn't suffice. That's when this token is moved into another table and tracked with a `user_id` instead. |
| 65 | + |
| 66 | +## Why do we need passwords? |
| 67 | + |
| 68 | +The token system developed above is very robust, but it isn't always an acceptable security measure (at least not alone). That's because, if a user loses the token, it is next to impossible (especially if it was generated with CSPRNGs with reasonable size) to gain access back to their lists using today's computing powers. |
| 69 | + |
| 70 | +So, maybe instead of a long random token, use a password? We can ask the user when they land on our page for a passcode (aka password). And we check the database if we can find a list where `password = USER_SUBMITTED_PASSCODE` then display them. If not, that means they are a new user. |
| 71 | + |
| 72 | +Indeed this works, passwords are okay and a perfectly viable and widespread approach. Keeping in mind that users tend to use easy to remember words, dates, phone numbers, and the like. This makes passwords vulnerable to brute-force attacks. It would be relatively harder than brute-forcing emails, but still easy to guess, and very easy for computers to break by checking every possible combination of words, dates, numbers, and even relatively harder passwords using a technology called **rainbow tables**. |
| 73 | + |
| 74 | +Hence, there are two things to remember about passwords: |
| 75 | + |
| 76 | +- They require validation to prevent brute force attacks (thus preventing easy to guess passwords) |
| 77 | +- Use salt and hash to prevent rainbow attacks |
| 78 | + |
| 79 | +## Security Checklist |
| 80 | + |
| 81 | +### Storing Passwords |
| 82 | + |
| 83 | +**Never** save the password as plain text in a database. Always use industry-standard cryptographic algorithms like bcrypt to hash and salt passwords. More on that later. |
| 84 | + |
| 85 | +### Password Policy |
| 86 | + |
| 87 | +You need to implement and **enforce** a password validation policy. It can contain: |
| 88 | + |
| 89 | +- The minimum acceptable combination of characters (lowercase, uppercase, special characters) in a password |
| 90 | +- Minimum length |
| 91 | +- Expiry dates (if necessary) |
| 92 | + |
| 93 | +### Use Federated Identity Management |
| 94 | + |
| 95 | +Federated identity management is a configuration that can be made between two or more trusted domains to allow consumers of those domains to access applications and services using the same digital identity. Such identity is known as federated identity, and the use of such a solution pattern is known as identity federation. |
| 96 | +An example of this is to offer people to sign in with Google, or Github. Here, Google is an identity provider (IdP). |
| 97 | + |
| 98 | +Many benefits come with this: |
| 99 | + |
| 100 | +- User convenience, they don't have to remember lots of passwords and fill preliminary registration forms. |
| 101 | +- Delegate account and password management overhead to the identity provider. |
| 102 | +- Sometimes, you can even skip email validation logic since that has been already done. |
| 103 | +- Avoid privacy compliance burden. |
| 104 | + |
| 105 | +There are three protocols for federated identity: |
| 106 | + |
| 107 | +- SAML |
| 108 | +- OpenID |
| 109 | +- OAuth |
| 110 | + |
| 111 | +We will cover OID and OAuth later in this module. |
| 112 | + |
| 113 | +### Database security |
| 114 | + |
| 115 | +You need to ensure basic isolation of your database servers, use firewalls to limit access, protect and encrypt backups, and opt-in for database as service (DBaaS) providers when possible. |
| 116 | + |
| 117 | +### API Throttling (Rate Limiting) |
| 118 | + |
| 119 | +This is a wide subject too and it can be applied to different elements of security. It can protect your server from some types of DDoS and DoS attacks, as well as thwarts brute-forcing attempts to break through your security. You can also limit how many login attempts are allowed, and then block attempts for a pre-defined cool-off period. |
| 120 | + |
| 121 | +### Secure HTTP (HTTPS) |
| 122 | + |
| 123 | +As you've known know, HTTP is a protocol to exchange messages between a client and server. And since all your messages will go through the network connection (a wire), an attacker anywhere on the network can sniff (listen to) all your messages, including passwords, tokens, etc. en route. |
| 124 | +To make these messages obscure (or gibberish), you need to encrypt them using encryption technology. That's when the protocol is upgraded to SECURE status. |
| 125 | + |
| 126 | +The process is usually done by obtaining a certificate from a Certificate Authority (CA) that issues the digital identity for the browsers to trust. The certificate contains a private key that is used by the server to encrypt and decrypt the messages. |
| 127 | + |
| 128 | +### Test your code |
| 129 | + |
| 130 | +Testing the code correctly to ensure it achieves its intended purpose around normal and abnormal scenarios. |
| 131 | + |
| 132 | +For instance, if you define an endpoint is only intended for admins, you need to test that it: |
| 133 | + |
| 134 | +- Rejects gracefully any request from non-admin users |
| 135 | +- Rejects requests from unauthenticated clients |
| 136 | +- When if a token has expired, it redirects the request correctly |
| 137 | +- These are some examples of test cases. You need to account for edge cases in your logic as well. |
| 138 | + |
| 139 | +### Update your code and libraries |
| 140 | + |
| 141 | +Cyberattacks evolve, as well as the tools to carry them out. A library used today can be broken tomorrow. You need to ensure that you always update your libraries and apply the necessary patches to your code so it follows up-to-date security practices and guides. |
| 142 | + |
| 143 | +Cybersecurity is an unattainable quest, so we will never be 100% secure. We just aspire to be as close as possible to that. |
| 144 | + |
| 145 | +## Module overview |
| 146 | + |
| 147 | +In this module, we will cover best practices to establish and implement most of the tips shared above. We will focus on current industry standards and libraries to ensure our built web apps are running with the best security practices available. We will also explore authorization and validation as means to security and data integrity. |
0 commit comments