My react typescript app fails to load resources from API and it returns this error:
Content Security Policy: The page’s settings blocked the loading of a resource at http://api.xxxxx.com/v1/blogs (“default-src”).
I am using axios and this is how my request looks like:
const headers = {
'Content-Type': 'application/json',
'Content-Security-Policy': 'default-src \'self\'',
'Access-Control-Allow-Origin': '*',
};
const { data } = await this.$http.get<Item>(url, { headers });
I also added this line in the index.html
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
It allows in dev mode, but I deployed using azure static web apps and that is where it fails loading the resource, I was thinking if it has to do with any azure configs?
Edit1
Tried all the suggestions from this question but haven't solved the problem.
Related
I'm building a program that uses helmet as a security layer on the server side. I fetch from the GitLab API. And I use socket.io to communicate with gitlab. I also use ngrok to get a temporary url for gitlab to send requests to while I work on localhost.
When opening the application, every few seconds I get this error:
Refused to connect to 'https://.ngrok.iosocket.io/' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.
Why does this happen? I tried to add the ngrok url as connect-src but that didn't help.
This is what my helmet CSP looks like:
app.use(helmet())
app.use(
helmet.contentSecurityPolicy({
directives: {
...helmet.contentSecurityPolicy.getDefaultDirectives(),
'script-src': ["'self'", 'code.jquery.com', 'cdn.jsdelivr.net', "'unsafe-eval'"]
}
})
)
I'm using axios to make requests to fetch the data from my external API (it's HTTP AWS server with ExpressJS and Nginx). I tested it on my local machine with the web version of my Ionic app and everything is working expected. Also I can fetch data if I'm using my phone's browser.
Same goes with postman, I can fetch data without any problems.
The only place where these requests don't work is the actual device. Looking at the Android Studio console the error is: "Msg: Network Error" (failing to figure out how to get more from axios error object).
I configured CORS following the official Ionic documentation. I've set all needed origins and options (can't use * origin because I have to use credentials with my requests). Express configuration looks like this:
const corsOptions = {
origin: [
'http://localhost:8100',
'http://localhost:8080',
'http://localhost',
'capacitor://localhost',
'ionic://localhost',
],
credentials: true,
optionsSuccessStatus: 200,
exposedHeaders: ["set-cookie"]
}
// Enable preflight requests for all routes
app.options('*', cors(corsOptions));
app.use(cors(corsOptions));
On the client (request example):
try {
const response = await axios('http://my.api.url', {
method: 'get',
withCredentials: true,
headers: {
'Accept': 'application/json'
}
});
const data = response.data;
// Do something with the data
} catch(error) {
console.log(error);
};
I think it has something to do with Capacitor, maybe there is a problem with non-https API (but then the question is why does it work with the web version). I tried disabling credentials for my requests but the error reoccur. Also removing Nginx doesn't seem to change anything.
Update: Also the axios says the request is sent but the server didn't respond.
I sorted it out, I had to do following.
Had to add a SSL to my web server (I used letsencrypt).
Had to add this to capacitor.config.json:
"server": {
"allowNavigation": [
"my.api.url"
]
}
Official Capacitor Documentation - Common Configuration
I have a vue.js cli client which consumes an API which resides on Azure (I have developped both client and API).
When I run the client in development mode (npm run serve) my API is correctly responding with Status Code 200. However, when I build the production version (npm run build) and run the dist version locally (serve -s dist), my API call is rejected (400 bad request).
It seems that the build process is doing compiling something differently.
My ApiService.js code snippet:
import axios from 'axios'
const apiURL = 'https://my-api.azurewebsites.net/'
const apiClient = axios.create({
baseURL: apiURL,
withCredentials: false,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
})
userLogin(credentials) {
return apiClient.post('/login', credentials)
}
This is the diff of the two API calls
When I call the API in production mode the browser reports a cors issue:
Access to XMLHttpRequest at 'https://my-api.azurewebsites.net/login' from origin 'http://www.mysite.ch' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I spent many ours on the web to find a solution, but I was not successful. Any hints are welcomed.
I suspect it is working locally because your local domain is passing the CORS request. Ultimately this is just a CORS configuration issue. Your production domain has not been whitelisted. I'm not sure what your back-end is or how Azure affects it, but you need to whitelist your production domain for API consumption.
This is an example of setting a CORS policy in Express: https://flaviocopes.com/express-cors/
Just make sure you don't allow ALL origins as that is a security risk.
I run my project on my Mac OS device and I want to access from another laptop.
the first device gets all responses from the server as well:
http://192.168.1.101:3000/
but another laptop I got this error message:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://www.shadyab.com/api/Api/coupons. (Reason: missing token ‘access-control-allow-origin’ in CORS header ‘Access-Control-Allow-Headers’ from CORS preflight channel).
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data',
'Access-Control-Allow-Origin': '*'},
body: JSON.stringify(formData)
};
Add
headers: {'Access-Control-Allow-Origin': '*'}
to your server where the API is fetching from
I think this is something related to your backend sometimes backend only allows some origins and your new front-end domain must be added to Access-Control-Allow-Origin
but sometimes that could be related to the webserver and its configuration needs to be change, for example if you are using Apache .htaccess file must be changed
Assuming you are using cors() in the backend (like in a node server).
Then in your react app, what you can do is setup proxy for the api endpoints.
in the src directory create a file named setupProxy.js. What it does is, create proxies for your api endpoints. What you can do is something like below
setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
const BACKEND_HOST = process.env.REACT_APP_BACKEND_HOST || 'localhost';
const BACKEND_PORT = process.env.BACKEND_PORT || 8000;
module.exports = function(app) {
app.use(
'/',
createProxyMiddleware({
target: target,
changeOrigin: true,
logLevel: 'debug'
})
);
/**
* You can create other proxies using app.use() method.
*/
};
Note: You do not need to import this file anywhere. It is automatically registered when you start the development server.
And after creating proxies, you should send request to your backend server only specifying the endpoints. Like if you want to send request you should use / instead of http://localhost:8000.
Let me if it works. Thanks
I have a question regarding the implementation of cors in a ASP.NET Web API.
The reason I am turning to SO is that I've tried searching everywhere, and found a lot of tutorials and answers, but none of those seem to work for me.
Setup:
Web Application (HTML5, JS) running on XAMPP (192.168.1.101:8080)
API (ASP.net) running on IIS Express (Integrated with VS2013) (192.168.1.101:52126)
The web application makes ajax calls to the API as shown in the code block below.
$.ajax({
data: JSON.stringify(data),
type: 'POST',
url: 'http://localhost:52126/api/controller/action',
dataType: 'json',
contentType: 'application/json',
processData: false,
headers:
{
"Authorization": "Basic Base64Encrpytion"
},
success: function(data)
{
// Handle success
},
error: function(data)
{
// Handle error
}
});
This all works perfectly in localhost including OPTION preflight. But when I start the web application from a other device in the same local network, the preflight fails and ofcourse if the preflight fails the rest of the calls get canceled as well.
Error:
When trying to query the API from another device (192.168.1.100) in the same network using the web application the following responses are generated:
Console
OPTIONS http://192.168.1.101:52126/api/controller/action 400 (Bad Request)
OPTIONS http://192.168.1.101:52126/api/controller/action No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.168.1.101:8080/' is therefore not allowed access.
XMLHttpRequest cannot load http://192.168.1.101:52126/api/controller/action. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.168.1.101:8080/' is therefore not allowed access.
Response Header
Connection: close
Content-Length: 334
Content-Type: text/html; charset=us-ascii
Date: Wed, 05 Mar 2014 09:29:46 GMT
Server: Microsoft-HTTPAPI/2.0
The response header does contain the Access-Control-Allow-Origin "*" header when testing the web application and API on localhost.
Solutions I have tried:
Adding the code below to each class that needs to be reached from outside the domain.
[EnableCors(origins: "*", headers: "*", methods: "*")]
Adding the code below to the Web.config file.
<httpprotocol>
<customheaders>
<add name="Access-Control-Allow-Origin" value="*"></add>
</customheaders>
</httpprotocol>
Adding the code below to the WebApiConfig file.
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
Adding the code below to the applicationhost.config
<binding protocol="http" bindingInformation="192.168.1.101:52126:*" />
The following setting is set to true
jQuery.support.cors = true
I have also tried to override the preflight handler, but that seemed to fail as well.
Wasting two days on this problem, i think i've solved it.
Since i am developing on a workstation in a corporate network i don't have local administrator rights. Which means i have to run Visual Studio 2013 in Administrator Mode. That way IIS Express can run on the network instead of only localhost.
In the applicationhost.config i did the following:
<binding protocol="http" bindingInformation="*:50157:localhost" />
<binding protocol="http" bindingInformation="*:50157:192.168.1.101" />
Which obviously fails because they are both assigned to the same port. So i changed that to:
<binding protocol="http" bindingInformation="*:50157:localhost" />
<binding protocol="http" bindingInformation="*:50158:192.168.1.101" />
TL;DR
Make sure you run Visual Studio in adminstrator mode or just obtain local administrator rights.
Use a different port for each ip.