DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for 72-Nodejs Course 2023: The Bloody Cors
Hasan Zohdy
Hasan Zohdy

Posted on

72-Nodejs Course 2023: The Bloody Cors

What is CORS?

CORS stands for Cross-Origin Resource Sharing. It is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served. A web page may freely embed cross-origin images, stylesheets, scripts, iframes, and videos. Certain "cross-domain" requests, notably Ajax requests, are forbidden by default by the same-origin security policy.

In Simple Words?

Simply put, Cors allows us to whitelist the domains that can access our API. It is a security mechanism that prevents unauthorized access to our API.

For example, our nodejs application is going to be API application, so we can define who is allowed to access our API. For example, we can allow localhost:3000 to access our API, but we can also allow localhost:3001 to access our API. So, we can define a list of domains that are allowed to access our API.

So it is a sort of a middleware as well such as our previous throttle article one.

How does Cors work?

It basically has multiple functionalities, it can white/black list any of the following:

  • Certain Domains
  • Certain HTTP Methods
  • Certain HTTP Headers

What is an Origin?

An origin is a combination of URI scheme, host name, and port number. For example, https://www.example.com:443 is an origin. The origin of a resource is the origin of the server that served the resource. For example, if you visit https://www.example.com:443 and it returns a resource that has a URL of https://www.example.com:443/foo/bar, the origin of the resource is https://www.example.com:443.

So we can simply say that origin is the combination of protocol, domain/ sub-domain and port.

Preflight Request

When a request is made to an API, the browser will first send a preflight request to the API to check if the request is allowed. If the request is allowed, then the browser will send the actual request.

What is a Preflight Request?

A preflight request is simply a OPTIONS request that is sent to the API to check if the request is allowed. If the request is allowed, then the browser/client side will send the actual request such as GET, POST, PUT, DELETE etc.

That's where mostly the OPTIONS request method is used in.

How to Implement?

We can use fastify-cors plugin to implement Cors in our application.

Installation

yarn add @fastify/cors
Enter fullscreen mode Exit fullscreen mode

Usage

As mentioned in the docs, we need first to register our plugin and its options.

We're going to use the dynamic import as we did earlier to import our plugin.

// src/core/http/plugins.ts
import fastifyJwt from "@fastify/jwt";
import fastifyMultipart from "@fastify/multipart";
import { registerPlugin } from "./server";

export default async function registerHttpPlugins() {
  // πŸ‘‡πŸ» register rate-limit plugin
  await registerPlugin(import("@fastify/rate-limit"), {
    // max requests per time window
    max: 10,
    // maximum time that is will allow max requests
    timeWindow: 60 * 1000,
  });

  // πŸ‘‡πŸ» register cors plugin
  await registerPlugin(import("@fastify/cors"), {
    // options list
  });

  // import multipart plugin
  registerPlugin(fastifyMultipart, {
    attachFieldsToBody: true,
  });

  // use the jwt plugin with your preferred secret key
  registerPlugin(fastifyJwt, {
    secret: "my-secret",
  });
}
Enter fullscreen mode Exit fullscreen mode

Nothing new here, we just imported our new cors plugin.

Options

We can pass options to our cors plugin, for example, we can allow localhost:3000 to access our API.

// src/core/http/plugins.ts
import fastifyJwt from "@fastify/jwt";

/// ...

// πŸ‘‡πŸ» register cors plugin
await registerPlugin(import("@fastify/cors"), {
// options list
origin: ["http://localhost:3000"],
});
Enter fullscreen mode Exit fullscreen mode

In the previous code, we allowed localhost:3000 to access our API, so any other origin will not be allowed to access our API.

Allowing All Origins

We can also allow all origins to access our API, but this is not recommended as it is a security risk.

// src/core/http/plugins.ts
import fastifyJwt from "@fastify/jwt";

/// ...

// πŸ‘‡πŸ» register cors plugin
await registerPlugin(import("@fastify/cors"), {
// options list
origin: "*",
});
Enter fullscreen mode Exit fullscreen mode

This will allow all origins to access our API.

Black/White Listing Origins

The plugin doesn't give as the ability to whitelist/blacklist certain HTTP methods, so we need to do it manually, this can be done by using custom origin function.

// src/core/http/plugins.ts
import fastifyJwt from "@fastify/jwt";

/// ...

// πŸ‘‡πŸ» register cors plugin
await registerPlugin(import("@fastify/cors"), {
// options list
origin: (origin, callback) => {
  // whitelist certain domains
  if (origin === "http://localhost:3000") {
    callback(null, true);
    return;
  }

  // blacklist certain domains
  if (origin === "http://localhost:3001") {
    callback(new Error("Not allowed"), false);
    return;
  }

  // allow all origins
  callback(null, true);
},
});
Enter fullscreen mode Exit fullscreen mode

Of course we are not going to use it like this, i'm just giving an example of how we can implement it later, this can be in our next Break article or so.

Why am i calling it Bloody CORS? 😁

Well, because when i started working with APIs, it was really pretty annoying to me to understand how it works and apply it with my Client side applications that connects to my API Applications, i was always getting an error message because of Cors says: No 'Access-Control-Allow-Origin' header is present on the requested resource.

That's why i was (and still) calling it Bloody CORS 😁

🎨 Conclusion

In this article, we learned how to implement Cors in our application, we also learned what is Cors and how it works.

We didn't set any configurations yet for our Cors plugin, we will do it later as we go through our application.

β˜•β™¨οΈ Buy me a Coffee β™¨οΈβ˜•

If you enjoy my articles and see it useful to you, you may buy me a coffee, it will help me to keep going and keep creating more content.

πŸš€ Project Repository

You can find the latest updates of this project on Github

😍 Join our community

Join our community on Discord to get help and support (Node Js 2023 Channel).

🎞️ Video Course (Arabic Voice)

If you want to learn this course in video format, you can find it on Youtube, the course is in Arabic language.

πŸ“š Bonus Content πŸ“š

You may have a look at these articles, it will definitely boost your knowledge and productivity.

General Topics

Packages & Libraries

React Js Packages

Courses (Articles)

Top comments (0)

11 Tips That Make You a Better Typescript Programmer

1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields

...

Read the whole post now!