Arcades
Arcades

Reputation: 150

Nodejs API : CORS seems to be enabled by default

Here is my problem: I have a site exemple.com and a node server where is my API running on exemple.com:3000. I want my API to be accessible only by exemple.com.

So I thought that Same-Origin Policy would have block every request from every site except mine if I send in the response the header : Access-Control-Allow-Origin: https:exemple.com.

The problem is that if I call the url : http://exemple.com:3000/api/v1/test/search on another site, I have the error:

Failed to load https://exemple:3000/api/v1/test/search: The 'Access-Control-Allow-Origin' header has a value 'https://exemple.com' that is not equal to the supplied origin. Origin 'http://randomsite.com' is therefore not allowed access.

But in the network tab, I have the response with a 200 status and all the results.

How is it possible to have the error and the result at the same time ? Here is my code :

app.js

const corsApiOptions = {
  origin: 'https://exemple.com',
  originSuccessStatus: 200,
};

app.use('/api/v1', cors(corsApiOptions), api);

routes/api.js

  const express = require('express'); const mongoose =
     require('mongoose'); const mongoosastic = require('mongoosastic');
     const AssoSchema = require('../schemas/assoSchema');

    const router = express.Router();

     router.post('/assos/search', (req, res) => {   let { query } =
     req.body;   if (query && query.length > 0) {
         query = query
           .split(' ')
           .map(el => `${el}~`)
           .join(' ');

        mongoose.connect('mongodb://localhost/mydb');
        AssoSchema.plugin(mongoosastic);

         const Asso = mongoose.model('asso', AssoSchema, 'assos');
         Asso.search(
           {
             query_string: { query },
           },
           { hydrate: true },
           (err, results) => {
             if (err) res.json({ error: err });
             res.json(results.hits.hits);
        },
       );   } else res.json(''); });

    module.exports = router;

Here are the results if I make an ajax request from the console of randomsite.com

//General
Request URL: https://exemple.com:3000/api/v1/test/search
Request Method: POST
Status Code: 200 OK
Remote Address: X.X.X.X:3000
Referrer Policy: no-referrer-when-downgrade
//Response Headers
Access-Control-Allow-Origin: https://exemple.com
Connection: keep-alive
Content-Length: 10022
Content-Type: application/json; charset=utf-8
Date: Fri, 30 Mar 2018 10:52:25 GMT
ETag: W/"2726-3/3tY5WvDTtyKm4KPBifg2dP7mI"
Vary: Origin
X-Powered-By: Express
//Request Headers
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Content-Length: 21
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Host: exemple.com:3000
Origin: http://randomsite.com
Referer: http://random.site.com/
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
//Form Data
query: random search

And in the preview tab I can see all my 10 results in json.

I want my api to accessed only from exemple.com, can someone help me on that ?

Upvotes: 1

Views: 631

Answers (1)

Quentin
Quentin

Reputation: 944036

But in the network tab, I have the response with a 200 status and all the results.

How is it possible to have the error and the result at the same time ?

The Same Origin Policy prevents JavaScript (embedded in a web page on a different origin) from reading the data in the response.

It is enforced by the browser.

It doesn't prevent the request being made.

It doesn't prevent the browser from getting the response.

It doesn't prevent the owner of the browser from seeing the response through other means (such as the Network tab) and even if it did, they could just make the HTTP request using another tool, such as cURL.

CORS allows a server to tell the browser to relax the Same Origin Policy and allow the JavaScript access to the data.

I want my api to accessed only from exemple.com, can someone help me on that ?

This isn't possible.

JavaScript on other origins won't be able to read the data directly, but it does nothing for non-JS approaches or indirect (e.g. via a proxy) approaches.

Upvotes: 2

Related Questions