Content Security Policy issues with new form - node.js

What is the easiest way for me to set the content security policy for a new form I am using? I have a frontend to backend form working for my registration but this form is a lot more complicated and is throwing me the errors below. I am aware this is to do with webpack and I have tried inserting code into my publ;ic index.html file which just stopped the page from rendering.
Would this have anything to do with my CORS settings in the backend? I have the below code which references headers and the I have been getting error messages about setting headings in other forms that I am having the same issues with.
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header(
'Access-Control-Allow-headers',
'Origin, X-Requested-With, Content-Type, Accept',
);
next();
});

The errors described have nothing to do with your CORS settings in the backend. They are related to CSP (Content-Security-Policy) header, which you, it would seem, do not use. But for nonexistent pages node JS is published CSP header on its own.
Pay attention to status code 404 Not Found. If you do not handle this kinds of errors, nodeJS uses own finalhandler to carry out of those by default.
Last versions of this finalhandler publish the CSP default-src 'none'; all the nitty-gritty is here.
Looks like you do not serve routes to root / folder in you server config, therefore /favicon.ico and similar urls are not found -> finalhandler publishes default-src 'none'; -> you observe CSP violation in the browser console (along with the 404 not found messages).
You have to add into server.js something like that:
app.use(express.static('client/public'));
app.get("/favicon.ico", (req, res) => {
res.sendFile(path.resolve(__dirname, "/favicon.ico"));
});
The above will solve the issue with "/favicon.ico Not Found", for other "non existent" Urls you need to add routes too.

Related

CORS on Azure Web App returning error: No 'Access-Control-Allow-Origin

I have an Azure static web app running my frontend and an Azure web app running my backend. I've been using this app for a couple of months. Today, after deploying some changes, my backend has been responding with CORS errors. Specifically, the error is:
Access to XMLHttpRequest at 'https://memoriesforusbe.azurewebsites.net/auth?userEmail=xxxxxxxxxxxxxxx&userPassword=xxxxxxxxxxxxx' from origin 'https://www.memoriesforus.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
UPDATE: I did some more testing this morning and have found that the response is different depending on the user. This makes NO sense to me that a CORS response is based on the data being sent in? More confused than before.
The headers that I had in my node.js server file were:
res.header("Access-Control-Allow-Origin", "https://login.memoriesforus.com");
res.header("Access-Control-Allow-Origin", "https://www.memoriesforus.com");
To try to fix it, I added the following in hopes the wildcard might help.
res.header("Access-Control-Allow-Origin", "https://*.memoriesforus.com");
res.header("Access-Control-Allow-Origin", "https://memoriesforus.com");
I also noticed that Azure Web Apps has a blade for CORS. I tried adding my headers there and had the same result.
The error occurred on the login screen of the app. I have a couple of apis that don't require the user to be logged in or use tokens. So I tried those and they seem to be working. So I'm thinking it may have something to do with that?
I'm just very confused because the original request headers worked for so long. Is there something else I should be looking at that might cause this error? The changes I made in the backend were unrelated to CORS. Not sure if something changed on the app service? I also uploaded changes to the frontend. But the call to the api that is getting the error was also unchanged.
The whole CORS related section of the node.js server file currently looks like this:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "https://login.memoriesforus.com");
res.header("Access-Control-Allow-Origin", "https://www.memoriesforus.com");
res.header("Access-Control-Allow-Origin", "https://*.memoriesforus.com");
res.header("Access-Control-Allow-Origin", "https://memoriesforus.com");
res.header("Access-Control-Allow-Origin", "https://salmon-plant-09df42110.2.azurestaticapps.net"); //the auto generated name of the frontend on Azure
if(process.env.SERVER_STATUS === 'Dev' ) {
res.header("Access-Control-Allow-Origin", "*"); }
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
if (req.method === "OPTIONS") {
res.header("Access-Control-Allow-Methods", "PUT, POST, PATCH, DELETE, GET");
return res.status(200).json({});
}
next();
});
You may have zero or one Access-Control-Allow-Origin headers. You can't have two or more.
The * character is a special value meaning "any origin", it isn't a placeholder that can be included in the allowed origin as a wildcard for part of the origin.
To allow multiple, but not all, origins you need to:
Read the Origin request header
Compare it to whatever rules you care to write to see if it is an allowed origin
Include res.header("Access-Control-Allow-Origin", the_origin_request_header_value); if it is one
You appear to be using Express, if so the cors module will handle this for you (and allow you to specify valid origins as a list, a regular expression, or a custom function).
I found this article which ended with the problem being the data. So I created a new user and tried with that user. The api works fine. So I will close this question and work on why my data is giving a CORS error. Never occurred to me that it could be the data itself.

How to configure Content-Policy-Security header on ExpressJs app?

I'm want to create a link in my website who download a PDF file but I get a white window with:
Cannot GET /file
and a Content Security Policy (CSP) error:
Content Security Policy: The page settings prevented a resource from loading at inline ("default-src").
I use ExpressJs and Nginx for the back-end.
I've tried to set CSP default-src header like this in my app.js file:
//Headers setup
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy',"default-src 'self' https://www.mydomain.fr");
next();
});
i've also tried to add this in my .conf file in Nginx:
add_header Content-Security-Policy "default-src 'self';" always;
It is still not working. Do you have any idea what is wrong?
My router:
const express = require('express');
const router = express.Router();
const fileController = require('../controllers/file');
router.get('/', fileController.getFile);
module.exports = router;
My controller:
const path = require('path');
exports.getFile = (req, res, next) => {
res.set({'Content-Type':'application/pdf'});
res.set({'Content-Disposition':'attachment, filename=file.pdf'});
const filePath = path.join(__dirname, '/public/documents/file.pdf');
res.download(filePath, 'file.pdf', (e) => {res.status(404).json({e: e})});
}
I guess your resource is embedded inline (see the csp error).
To allow that use unsafe-inline:
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy',"default-src 'self' 'unsafe-inline'");
next();
});
SabSab43, you have been given the correct leads in the comments and answers, but you shouldn't recklessly publish the CSP. You can publish CSP in several ways:
add_header in Nginx
HTTP header via res.setHeader()
specialized Helmet package
using <meta http-equiv='Content-Security-Policy' content="...CSP rules here..."> in the HTML code.
But if you do use all of above at the same time, you'll publish a several different CSPs and as result more restrictive one will acts.
Therefore remove all CSP you added and lets go step by step:
Do check the jonrsharpe's remark abt Helmet. The fact is that if you have Helmet 4 connected to Express, it issues the restrictive default-src 'self' policy by default.
Therefore after removing all your CSPs, check do you have CSP header in browser, tutorial is here. If CSP header is presents - some middleware (like Helmet) does publish it. You need to find it and modify the policy in it, or switch it off and use your res.setHeader(...)
If there is no header (and there is no meta tag either), publish the CSP with any of the methods, and add 'unsafe-inline' to it, as kmgt said. You need to have policy:
"default-src 'self' 'unsafe-inline' https://www.mydomain.fr"
to get rid of "The page settings prevented a resource from loading at inline ("default-src")"
Note that 'prevented a resource from loading at inline' can be about not only inline <script>, but about inline <style> too. But since you use `default-src', it covers both.
PS: Chrome's console more verbose than Firefox's one. If you fail to fix this issue, pls show the message about the blocking from the Сhrome's console - it will show the rules that block.
I've deleted all my CSP Rules (I don't use Helmet or any CSP dependencies) in my app and Nginx .conf file and when I look in browsers developers tools I see again the CSP Rule.
In chrome:
capture
In Firefox:
capture
therefore, I've tried to put this code:
app.use((req, res, next) => {
res.set({"Content-Security-Policy":"default-src 'self' 'unsafe-inline' https://www.myDomain.fr"});
next();
});
I've the same result than without the CSP Rules...
In Chrome I juste have a 404 error:
GET https://www.myDomain.fr/file 404 (Not found)
In Firefox
GET https://www.myDomain.fr/file [HTTP/1.1 404 Not found 96ms]
Content Security Policy: The page settings prevented a resource from loading at inline ("default-src").
The 404 is probably caused by the CSP Error...

CORS, Laravel Valet, and Socket.io

This feels like it's all way harder than it should be. I am working on an application for a client and am at the end of my rope trying to get this thing running locally. So, I am using Laravel(served through Valet on my mac) and am writing a Socket.io server for handling different dashboard events. Socket.io runs in an https configuration as it will in production and I've got it running on port 3001. I've got both serving content over https, resolved all configuration issues there. However, now I can not stop getting CORS errors whenever I try to connect.
Here is the error I am getting:
Access to XMLHttpRequest at 'https://ags.test:3001/socket.io/?EIO=3&transport=polling&t=1605106550351-47' from origin 'https://ags.test' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I've done a fair bit of testing on this and found that if I do a GET request to the root (/) of the express server, it works fine and without CORS errors. However, the polling at the url posted in the error above is still providing the same CORS error.
If it isn't abundantly obvious by now, I'm fairly new to the node ecosystem. So what I'm caught up on is what's happening with CORS when it goes from calling 'https://ags.test:3001' to 'https://ags.test:3001/socket.io/*'. Or is it possible that express isn't handling the CORS for socket.io at all?
Something I've seen multiple times in other stackoverflow answers is something along the lines of (from the server) io.origins('*:*') to set the origin policy. However, I can't seem to find documentation on this and calling it (or any of the variations I've seen of it)
So you know what I've already tried, here the server configuration for my Socket.io express server:
app.use(cors());
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
// authorized headers for preflight requests
// https://developer.mozilla.org/en-US/docs/Glossary/preflight_request
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
app.options('*', (req, res) => {
// allowed XHR methods
res.header('Access-Control-Allow-Methods', 'GET, PATCH, PUT, POST, DELETE, OPTIONS');
res.send();
});
});
var options = {
key: fs.readFileSync('./ags.test.key'),
cert: fs.readFileSync('./ags.test.crt'),
origins: '*:*',
cors: true,
};
const server = https.createServer(options, app);
I've also made adjustments to my laravel site config in valet as seen here https://gist.github.com/poul-kg/b669a76fc27afcc31012aa0b0e34f738 but applied directly to my site-specific config at ~/.config/valet/Nginx/ags.test and restarted.
As you can see, I've tried quite a few different things and am at the "throw everything at the wall to see what sticks" stage of trying to get these servers communicating. Any recommendations?
Okay, took me way too long to figure out what I was missing. Old stackoverflow answers show configuration methods that are no longer supported in Socket.io v3.
Here's what I was missing to configure this for the most recent version of Socket.io as of the date of posting.
const server = https.createServer(options, app);
const io = require('socket.io')(server, {
cors: {
origin: 'https://ags.test'
}
});

CORS policy issue

I am in a team doing a client-server application. We are using Node.js (v12.18) in the backend as an API, and React (v16.13) for the frontend. Recently I've found this bug related to the CORS policy. I'm trying to send a POST request, deleting one resource in the database and when trying to delete it, this is the error I get:
Access to fetch at 'http://localhost:8080/clientes/eliminar' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
As far as I researched in forums and discussions I always find the same resolution, which is using the "Access-Control-Allow" headers, but we are already using them. I tried to change the POST method by a DELETE method when doing the request, but I find the same issue.
The headers that we are currently using in the backend, in case someone wonders what we have.
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Methods", "GET, POST");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, token");
next();
});
The sites I visited in order to solve the problem were pretty much the same as this one
TYSM for reading until here and ask for more information you need. Every piece of help is appreciated.
Have you already tried to add CORS to the project and use it as a middleware?
//...
const cors = require('cors')
//...
app.use(cors())

Angular on localhost gets 404 when consuming GET api from different localhost PORT - CORS issue?

Ever since I switched to the database URL from the in-memory-web-api URL, the Angular app's JavaScript console gives me a 404 error
JavaScript console output 404 error
I've got my angular app running on lite-server using localhost:3035/
I've got a mongodb/nodejs/express database running on localhost:3039/
My angular app was "GET"-ing just fine using the in-memory-web-api url 'api/loggerData'
Any thoughts? Is it CORS? Something else? Do I need to configure the lite-server on the angular side as well?
Here's my angular Code:
private loggerUrl = 'localhost:3039/read/getall/';
getLoggerData(): Promise <Dataset[]> {
return this.http.get(this.loggerUrl)
.toPromise()
.then(response => response.json().data as Dataset[])
.catch(this.handleError);
}
Also, I've tried implementing some CORS solutions on the database side that haven't affected anything -
here's some of the database code I modified:
var app = express();
app.use(function (req, res, next) {
//Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3035');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods',
'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
No collection errors usually means, that you have left hanging some the equivalent of:
InMemoryWebApiModule.forRoot(InMemoryDataService)
in your ngModule, which interferes when you try and make "real" http-requests. So remove that from your ngModule and you should be good to go! :)
After this you might still run into problems with CORS, but this should fix the current error you get :)
And as mentioned by echonax, you should use the complete url, with http included:
private loggerUrl = 'http://localhost:3039/read/getall/'

Resources