javascriptnode.jscorsfastify

Fastify Error: Access to XMLHttpRequest at api-dev.example.com from origin dev.example.com has been blocked by CORS policy


I have a Node.js(v20.10.0) backend server using Fastify(v4.26.2) as the framework.

I have index.js as an entry point.

 import Fastify, { FastifyInstance, FastifyServerOptions } from 'fastify';
 import cors from '@fastify/cors';

 // Assuming other settings and configurations are already written.
 fastify.register(cors, {
    origin: "https://dev.example.com",
    credentials: true,
 });

I have a GET API called for listing users https://api-dev.example.com/api/v1/users working fine.

But the issue comes with POST API, where I can create a user https://api-dev.example.com/api/v1/create-user.

When using any POST API, I am getting CORS Error

Access to XMLHttpRequest at 'https://api-dev.example.com/api/v1/create-user' from origin 'https://dev.example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests

I tried multiple approaches and still got the same error.

fastify.register(cors, {
    origin: "*",
    credentials: true,
 });

By the error, I can understand that the OPTION request is getting in response headers Access-Control-Allow-Origin: * that's why I am getting this error.

But in all GET API response headers Access-Control-Allow-Origin: https://dev.example.com

I am not sure why the OPTION request before the POST request Access-Control-Allow-Origin is *


Solution

  • If your GET request is working fine, but you encounter issues with POST or PATCH requests, then according to your error

    Access to XMLHttpRequest at 'https://api-dev.example.com/api/v1/users' from origin 'https://dev.example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests
    

    This error indicates that the browser is sending an OPTIONS request to the server with the 'Access-Control-Allow-Origin' header set to wildcard '*', while your server only accepts specific origins.

    The reason behind this is that every POST and PATCH request initiates a preflighted request. Unlike simple requests, for "preflighted" requests the browser first sends an HTTP request using the OPTIONS method to the server to determine if the server is opting in to receiving a cross-origin POST or PATCH request from server

    to fix this you can try adding, optionsSuccessStatus: 200 in your cors options like shown below

    fastify.register(cors, {
      origin: "https://dev.example.com",
        credentials: true,
        optionsSuccessStatus: 200,
      });
    

    With optionsSuccessStatus: 200, the server responds with a 200 OK status code for successful preflight requests. This indicates to the browser that the server is configured to accept cross-origin requests.

    Now that the server has acknowledged the successful preflight requests, your POST and PATCH methods should function correctly without encountering CORS-related issues.


    edit: well one thing I noticed

    since POST or PATCH request will trigger a preflight request with OPTION method I noticed without optionsSuccessStatus: 200 in the chrome network tab For the OPTIONS method, the request header had Access-Control-Allow-Origin: "*", whereas for the POST method, the request header had Access-Control-Allow-Origin: "https://dev.example.com".

    and this is what the CORS error says in this case

    Access to XMLHttpRequest at 'https://api-dev.example.com/api/v1/users' from origin 'https://dev.example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests
    

    After adding optionsSuccessStatus: 200 to the configuration, both the OPTIONS and POST requests had the request header Access-Control-Allow-Origin: "https://dev.example.com". In this case, the OPTIONS method also had the header Access-Control-Allow-Origin: "https://dev.example.com" instead of the wildcard * as it did previously.

    so for this, we have to take care!