Security Overview

We've touched upon some aspects of security within this book already. We've discussed how HTTPS/TLS works, how to store passwords safely, and introduced some basic concepts in cookie management. We talked about privacy on the web too, which is highly related to security principles. In this chapter we will dive deeper into some of the more important security concerns that you should consider when implementing a web application.

Pro Tipđź’ˇ This chapter does not attempt to cover all of the various security concerns that you, as a web user should consider. As a user of the web, perhaps your biggest concern should be social engineering - phishing attacks and the like. This chapter is about how to build your application such that it is less likely to be hacked, not how you yourself can protect yourself on the web. As a user of the web though, you should take your personal security (and privacy) very seriously however. By learning just how difficult it is to implement security, my hope is that you will double-down on your efforts to use the web safely yourself!

Web security is a huge topic, there so much detail and so much to think about! This chapter will serve as an entry point, a bare minimum for developing secure applications. This goal is to get you thinking - not to cover every detail. As you start to think about security, and how to protect your applications, you will start to see more attack vectors. You'll wonder about how to protect yourself.

Your first stop: OWASP. The Open Web Application Security Project provides an incredible amount of information to web developers, and is constantly updated to help developers just like you. OSWAP publishes a Top Ten list of common security concerns, and they also publish a fabulous resource for anyone looking to understand security principles - the OWASP Cheat Sheet Series. The Cheat Sheet Series is a comprehensive guide on how to properly implement just about every security feature you can think of. We'll link to it a few times in this chapter, I highly encourage you to take a look.

Most security starts with the server. When working with Express, security often revolves around the effective use of middleware. Middleware in Express allows you to intercept and process requests and responses, making it a powerful tool for implementing security measures. For example, middleware can be used to sanitize user input, enforce authentication and authorization, and set HTTP headers to mitigate common vulnerabilities like cross-site scripting (XSS) or cross-site request forgery (CSRF). Throughout this chapter, we will explore how to leverage middleware to address these concerns and ensure your application adheres to best practices for secure development.

Here's a quick overview of what this chapter will cover:

HTTPS: The Security Foundation

HTTPS (HTTP Secure) provides the fundamental security layer for web applications by encrypting data transmitted between clients and servers. By implementing Transport Layer Security (TLS), HTTPS protects against network-level threats such as packet sniffing, man-in-the-middle attacks, and connection hijacking. When properly implemented, HTTPS ensures that sensitive data—like authentication credentials, personal information, and API tokens—cannot be intercepted during transmission.

However, it's crucial to understand what HTTPS does not protect against. While it secures data in transit, it offers no protection against application-level vulnerabilities, compromised endpoints, or attacks that occur after data decryption. A secure HTTPS connection to a vulnerable application still exposes users to significant risks. Furthermore, HTTPS doesn't verify the legitimacy of the receiving application's business logic or prevent malicious actions by authenticated users.

Cross-Site Attacks: XSS and CSRF

Cross-site attacks exploit the trust relationship between users and websites. Cross-Site Scripting (XSS) occurs when attackers inject malicious client-side scripts into web pages viewed by other users. These scripts can steal session cookies, redirect users to fraudulent sites, or manipulate page content. XSS attacks come in three main varieties: stored (where malicious code persists in a database), reflected (where malicious code travels in the request itself), and DOM-based (where client-side JavaScript manipulation creates vulnerabilities).

Cross-Site Request Forgery (CSRF) represents another class of attacks where malicious sites trick authenticated users into performing unwanted actions on sites where they're already logged in. For example, a user authenticated with their banking portal might visit a malicious site that triggers a hidden request to transfer funds. Without proper CSRF protections, the banking application would process this request as legitimate since it includes the user's authentication cookies.

Content Security Policies and Cross-Origin Controls

Content Security Policy (CSP) and Cross-Origin Resource Sharing (CORS) represent critical defense mechanisms for controlling resource interactions. CSP allows developers to specify which content sources the browser should consider valid, effectively blocking execution of unauthorized scripts and preventing most XSS attacks. By setting appropriate CSP headers, applications can restrict which domains can serve executable scripts, styles, fonts, frames, and other resources.

CORS, meanwhile, defines how browsers handle cross-origin requests, providing a framework to securely relax the same-origin policy when appropriate. It allows servers to specify which origins can access their resources, what HTTP methods are permitted, and whether credentials should be included in cross-origin requests. Together, CSP and CORS create boundaries that contain application behavior within expected parameters, significantly reducing the attack surface.

Client-Side Data Protection and Input Validation

A fundamental security principle is minimizing sensitive data exposure on client devices. Information stored in browsers—whether in cookies, local storage, or session storage—should be treated as potentially compromised. Authentication tokens should be short-lived, scoped appropriately, and never include sensitive information. When client-side storage is necessary, encryption and careful consideration of access patterns become essential.

Input validation represents another critical defense layer. All user-supplied data must be treated as untrusted, regardless of client-side validation. Server-side validation should verify data types, formats, ranges, and business rule compliance. Parameterized queries and ORM frameworks help prevent SQL injection, while proper encoding prevents command injection and XSS. The principle of least privilege should extend to user inputs, allowing only what is explicitly necessary.

Multi-Tenant Architecture: The Additional Security Dimension

In multi-tenant applications, where a single instance serves multiple customer organizations, security encompasses not just protecting against external threats but also maintaining isolation between tenants. Each request must be evaluated within its tenant context to prevent data leakage between organizations. This requires tenant-aware authentication, authorization checks on every resource access, and careful validation of all resource identifiers.

Unlike single-tenant applications, multi-tenant systems must implement security as a cross-cutting concern across all application layers. Every database query, API endpoint, and business logic operation must incorporate tenant context verification. Without this comprehensive approach, even applications that successfully defend against traditional web vulnerabilities may still suffer catastrophic data exposures across tenant boundaries, undermining the entire security model.