Repository navigation
Node: Add new Advanced Topics lesson #31398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
981bdfe
b389234
e614611
6ee6553
9ad84e1
ced9ce6
9e908d0
d4d551c
e23d25d
a7e9eb5
d03b6a3
51fca42
5301dd4
fb1b1e9
fb3d4d9
e4eba2d
6dace88
6b90b07
ad1ed02
390d744
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| ### Introduction | ||
|
|
||
| As you work on more sophisticated web applications, there are some further concepts that might be good for you to be aware of, which we've left until now to avoid rabbit holes. In this lesson, we'll briefly talk about some of them along with possible ways to incorporate them into your Express applications. | ||
|
|
||
| ### Lesson overview | ||
|
|
||
| This section contains a general overview of topics that you will learn in this lesson. | ||
|
|
||
| - Content Security Policy. | ||
| - Logging. | ||
| - Internationalisation. | ||
| - Cross-Site Request Forgery. | ||
| - Rate limiting. | ||
|
|
||
| ### Content Security Policy | ||
|
|
||
| Depending on the app you are building, chances are you might want to limit what kind of resources are allowed on it. [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) is a feature that allows you to restrict what resources are loaded on your pages. This is important because it can prevent a few common vulnerabilities: | ||
|
|
||
| - **Cross-site scripting (XSS)**: The most common reason why you would want to employ a CSP. By restricting how JavaScript could be loaded and/or injected into your app, you can protect your app and your clients. | ||
| - **Clickjacking**: Attackers could also embed certain HTML elements (such as an `<iframe>`), overlaying your UI and hiding what's really under it. A user clicks something, thinking it'll done one thing, but the real button underneath actually does something different instead, such as overlaying a fake "close" button over a "submit" button. | ||
|
|
||
| ### Logging | ||
|
|
||
| Logging information in your app can help you identify what your app is doing at any given moment and display some errors internally that will be helpful for debugging and/or providing some useful data analytics, such your app's traffic distribution, how long do users tend to stay on certain endpoints, etc. The main point about leaving a series of ongoing record is that you could look back and see what went wrong or right, like leaving an entry in your diary! | ||
|
|
||
| Logging could be as simple as a few `console.log()`s in certain routes or you could introduce an entire library like [pino](https://github.com/pinojs/pino) or [winston](https://github.com/winstonjs/winston) into your workflow. These libraries are often optimized for performance and can give you back a lot of detail that'll prove useful. | ||
|
|
||
| ### Cross-Site Request Forgery | ||
|
|
||
| Another very common exploit in the World Wide Web. Imagine you encountered a strange but very innocent looking website called `cutekittens.com`...until you inspect its HTML that looks like this. | ||
|
|
||
| ```html | ||
| <form action="https://my-bank.example.org/transfer" method="POST"> | ||
| <input type="hidden" name="recipient" value="attacker" /> | ||
| <input type="hidden" name="amount" value="1000" /> | ||
| </form> | ||
| ``` | ||
|
|
||
| Then, within that site, a small but very dangerous snippet of JavaScript is embedded and will be loaded if anyone clicked on it... | ||
|
|
||
| ```javascript | ||
| const form = document.querySelector("form"); | ||
| form.submit(); | ||
| ``` | ||
|
|
||
| Assuming you are still logged in and your banking app's cookies still persist, disaster has already been struck! "Wait, I just want to see kittens! Why is my money gone?!" Yikes, you don't want that, right? [Cross-Site Request Forgery (CSRF) attacks](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/CSRF) are just that: tricking a user into performing a state-changing request to a certain target site from a malicious site. In this case, a form was automatically submit the moment you landed on `cutekittens.com` and a banking transaction was silently performed. | ||
|
|
||
| So what could you do about it? One of the most common methods is to use a CSRF token. Every time you prompt your user to perform some state-changing request in your application, check for a hidden, unpredictable key (this could be embedded inside a `<form>` or an HTTP request header). Then, in your app, carry out the request if and only if the token is valid. | ||
|
Comment on lines
+28
to
+48
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A separate thing I want to also point out about this section is that it probably won't be clear to learners exactly where the bank site URL comes from. The point is that whoever made the malicious site knows the URL (and params) that could get them what they want, and that's why they crafted the request URL in that way (see https://stackoverflow.com/a/33829607 for more context). It's not just any ol' URL/request to some random site. |
||
|
|
||
| ### Internationalization | ||
|
|
||
| Eventually, you might want to adapt your app to a wider range of audiences around the world. [Internationalization (I18n)](https://learn.microsoft.com/en-us/globalization/methodology/software-internationalization) is a process of adapting your applications to different populations/languages. This could involve taking a look at a client's [Accept-Language header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept-Language) and serve the content in the language that they want to see. | ||
|
|
||
| For example, MDN can accommodate a wide range of languages! For example, <https://developer.mozilla.org/fr/> will display all your pages in MDN in French! C'est pratique, non? | ||
|
|
||
| ### Rate limiting | ||
|
|
||
| Just like how your city has speed limit signs, [rate limiting](https://www.cloudflare.com/learning/bots/what-is-rate-limiting) is a technique that tracks a user's number of requests and puts a limit on how many times they can access a resource, such as how many requests they're allowed per day. This becomes especially important as your API grows, protecting you from [Denial of Service](https://www.cloudflare.com/learning/ddos/glossary/denial-of-service/) attacks. | ||
|
|
||
| This is commonly employed on sensitive endpoints, like ones involving authentication. You might've faced a similar problem where, after a number of unsuccessful attempts of logging into an application, it will temporarily lock you out and remind you to try again after half an hour or so. This is rate limiting coming into play because we want to protect users from brute-force login attacks. Rate limiting can involve tracking both a user's IP address and their username and checking how many requests they have made before our application stops or slows them down before any more requests are made. | ||
|
|
||
| ### Conclusion | ||
|
|
||
| We covered quite a lot. Hopefully by being aware of these concepts, you are now able to imagine what goes on under the hood of the software you are using in your everyday life. | ||
|
|
||
| ### Assignment | ||
|
|
||
| <div class="lesson-content__panel" markdown="1"> | ||
|
|
||
| 1. [ExpressJS' security best practices](https://expressjs.com/en/advanced/best-practice-security/) can help you well in securing your Express app. This guide also suggests a few libraries that could be helpful, should you want to tighten up your app's security without doing everything from scratch. | ||
|
|
||
| </div> | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing I think makes this section incomplete is that it's not quite clear exactly where the learner stands in relation to all this.
e.g. from this section, I can absolutely see a learner going "how would I use a CSRF token here? I don't have anything to do with
cutekittens.comnormy-bank.example.org!"The example used here makes sense but it's the bank site's responsibility to implement anti-CSRF measures, not the user's responsibility.
This section needs to clearly frame things so that it's relevant to the learner and them building sites/servers. The problem is specifically that if they're building something, not using anti-CSRF techniques like CSRF tokens is what can allow a malicious site to make a malicious request. By using something like CSRF tokens, a malicious site can certainly try a CSRF attack on your site but since they won't have the correct token, the request will not succeed.
So this example can be kept but instead of saying "So what could you do about it?" (which makes it sound like the user is the one to protect the banking site), frame it as what the banking site could do to protect against CSRF.
Then expand by framing things for when the learner is making their own sites, and how they can use stuff like CSRF tokens to protect users of their sites from CSRF.