Using CORS on node.js server on a phonegap application - javascript

I am trying to connect my cordova/phonegap application with my node.js server. Problem is, I get this error "XMLHttpRequest cannot load http://127.0.0.1:1234/api/users. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:5000' is therefore not allowed access. The response had HTTP status code 500. " . I tried adding this middleware to my node.js server, entering my phonegap domain, then, just for testing purpouses of course, I figured I will allow ALL domains for CORS, still no luck. This is what I used on my node.js server:
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', '*');
// 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();
});
And I am doing a pretty simple AJAX request from my phonegap application, which I think is pretty much correct. I am getting this error on my phonegap app and on the node.js server console I get an error from one of the controllers, saying can't see property X of undefined, which undefined is my req.body. Here is the request:
var serverURL = 'http://127.0.0.1:1234';
var body = {
userId : '123A',
comment: {
from: '123B',
content: 'I am a new generation of 123! :)'
}
};
var bodyToString = JSON.stringify(body);
$.ajax({url: serverURL + "/api/plates", dataType: "json", type: "PUT", data: bodyToString}).done(function (data) {
alert(data);
});

Allowing * origin access on your node server is a bad idea. http://docs.phonegap.com/en/1.9.0/guide_whitelist_index.md.html you can declare all domains to be supported by your app in phonegap itself, using element in cordova.xml. have a look at this Phonegap Cross-domain AJAX POST Request not working on Android
Edit
:
From comment below: if you need to allow access to any origin from chrome just for development purpose there is a plugin https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi

Related

Is there an equivalent for fetch's "credentials: 'include'" or XMLHttpRequest's "withCredentials" for WebSocket?

I'm setting up a web service that provides both authentication and a WebSocket interface. The API of the server needs to be accessible cross-domain and still receive the cookie set for the server's domain. In fetch, this is possible with the option credentials: "include" and it works well. Is there an equivalent for WebSocket?
Basically, I have a Node.js server running on a.com:
let app = require("express")()
// ...
//headers
app.use((req, res, next) => {
console.log(req.headers)
console.log(req.protocol)
// Allow multiple origins from config
let origin = req.headers.origin
if (config.allowedOrigins.includes(origin)) {
res.setHeader("Access-Control-Allow-Origin", origin)
}
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
res.setHeader("Access-Control-Allow-Methods", "GET,PUT,POST,PATCH,DELETE")
res.setHeader("Access-Control-Allow-Credentials", true)
res.setHeader("Access-Control-Expose-Headers", "X-Total-Count, Link")
next()
})
// ...
app.ws("/", (ws, req) => {
const sessionID = req.sessionID // should be the same sessionID for requests from all origins
// ...
})
// ...
from web application hosted on b.com:
let socket = new WebSocket("wss://a.com") // should include cookie from a.com
This works well when I test it locally and everything's running on localhost, but fails when the web application is running on a different domain.
I'd like to have the possibility that the user logs in on a.com, but can use the same session for a WebSocket request from b.com.
I'm thankful for every suggestion!
I've figured this out by now. The following assumes that third-party cookies are enabled:
The default behavior, at least in all major browsers I've tested, is that the existing cookie will be sent with the WebSocket request (i.e. exactly as I wanted it). The browser I was using where I encountered the issue is Brave. Brave seems to have a bug that Cookies are not added to WebSocket connections. So it wasn't an issue in the first place, just a bug in the particular browser I was using.
When third-party cookies are blocked though (as they are by default in Safari), I don't think there is a way to achieve what I'd like to achieve.

Allow remote server to accept requests coming from localhost with params

I have my application running locally on my computer and it is trying to connect to my remote nodeJS/Express server. I have set the headers in my remote server.
Main question: How do I allow my remote server to accept requests coming from my localhost with parameters? People have told me that my request will not work because the requested URL and the server URL do not share the same domain. The request is coming from my localhost and it is trying to access my remote node/express server. This transaction works when I remove the params in the request but does NOT work when I have the params.
This is how I set headers in my remote server to accept all requests:
app.use(function (req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "http://localhost:9000");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
if(res.headersSent) {
console.log("Headers sent");
}
else {
console.log("Headers not sent");
}
next();
});
Also, the res.headersSent keeps evaluating to false even though I can see the headers set in my Google network tab. Why is this value returning false?
This is how I am making my GET request to my server from my localhost:
var req = $http({
url: 'https://20161128t135355-dot-jarvis-hd-live-2.appspot-preview.com/read-message',
method: 'GET',
cache: false,
params: {last_updated: last_updated_time}
});
This post was not helpful How to enable cross-origin resource sharing (CORS) in the express.js framework on node.js
I think the params is causing the error, because it works fine when I take it out. I get this error:
XMLHttpRequest cannot load https://20161128t135355-dot-jarvis-hd-live-2.appspot-preview.com/read-message?last_updated=0. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 502.
All the solutions say to add/set the header and as you can see I have done that but my application still gives me the same error when I include params in the request. What should I do differently?
So that means your problem is that your server side code throws an error when you add params to the request. You need to debug that. The CORS stuff is almost certainly irrelevant.
This issue is not a CORS issue, it has something to do with my params request. To fix this, I had to configure body-parser like so:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
This helps when sending JSON data to the client from the server or vice versa. You can find more information here: http://junerockwell.com/difference-parameters-query-strings-express-js/

No 'Access-Control-Allow-Origin' header is present on the requested resource when trying to connect to Raspberry

I'm working with my Raspberry Pi.
I have my raspberry Pi, that on the IP: 192.168.X.X/file.json give me a webpage containing data in json. While trying to built a web page that requests in that page with the following code:
$.getJSON('http://192.168.X.x:8080/file.json', function(data) {
//code }
It returns the an error on the browser:
XMLHttpRequest cannot load http://192.168.X.X:8080/file.json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
Can you tell me how to fix it?
And where to put the code to fix it?
Your issue is related to Cross-Origin Resource Sharing (CORS): basically, you cannot access a domain via Ajax if it's not allowed on the server side. This is a "security" feature on most modern browsers. You won't encounter this problem using command line such as curl or chrome's Postman extension.
Make sure the domain requesting the data (localhost) is allowed in the Access-Control-Allow-Origin header, as well as the http verb (GET, POST, PUT... or * for every http methods).
Basically, it comes down to add the two following headers to the http://192.168.X.x/ server's response:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
If you use node.js with Express, you can do the following :
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
// or res.header("Access-Control-Allow-Origin", "localhost");
res.header("Access-Control-Allow-Headers", "*");
next();
});
You need to configure your web server to set the appropriate CORS response headers.

XMLHttpRequest cannot load https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=

I am trying to integrate facebook login for my app in nodejs, angularjs using passport-facebook module.
I can intergrate facebook authentication without angularjs, but when i use angular http.get('/auth/facebook')
i am getting below error
XMLHttpRequest cannot load https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%…%2Flocalhost%3A1439%2Fauth%2Ffacebook%2Fcallback&client_id=xxxxxxxx. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:1439' is therefore not allowed access.
app.js:153 err
Below is my angular code
var headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Content-Type': 'text/html'
};
$scope.fblogin=function(){
// $window.location.href='/auth/facebook';
$http({
url:'/auth/facebook',
method:'GET',
headers: headers
}).success(function(data){
console.log(data);
}).error(function(){
console.log('err');
});
};
pp.config(['$routeProvider','$httpProvider',
function($routeProvider,$httpProvider) {
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.headers.common = 'Content-Type: application/json';
delete $httpProvider.defaults.headers.common['X-Requested-With'];
NodeJs
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
**Note:**I have tried changing multiple header changes for $http.get()
Solution:
The link https://www.facebook.com/dialog/oauth?... is not designed for calling it as ajax because it must REDIRECT user to facebook login page (so when you call it by ajax then redirect is impossible).
Instead of make ajax request just prepare in html proper element:
<a href="https://www.facebook.com/dialog/oauth?..." > ... </>
This works :)
This is what I have done to avoid Angular to call facebook auth dialogue API as AJAX request.
Use 'window.location="http://localhost:3000/auth/facebook"'; in your Angular Controller Function from where you send the request to your Express Server which contains passport.authenticate stuff.
Example:
$scope.authFacebook = function() { window.location="http://localhost:3000/facebook" }
You are attempting to make an ajax call to a URL and the browser is rejecting that ajax request because of cross origin security.
There are several possible reasons for this:
The domain of that URL doesn't allow cross origin requests.
You aren't making the request in a proper way for the cross origin request to succeed.
Your request is not formed properly (either targeted at the right URL or sent with the right options).
FYI, your node.js code where you set the allow-origin headers has absolutely nothing to do with the browser code attempting to send an ajax call to Facebook. That code would allow other people's web sites to make cross origin requests to your node.js server.
One thing that is a bit confusing about what you posted is that the URL of the $http() call you show is not the same URL as you are getting in the error message so I'm wondering if you're looking at the wrong code for the error.
This solution works for me, adding to cors to express app
var cors = require('cors')
var app = express()
app.use(cors())

Node/Express doesn't update the data model correctly

I have followed this Tutorial for creating a restful Api with Nodejs and Mongo. It works fine except a few problems.
My Player model is
var player = new mongoose.Schema({
name: String,
email: String,
score: String
});
When I try to post data through Postman extension on Chrome/Firefox, I cannot post the data. The response is the following
"__v":0,"_id":"54fed7cf5dde9b1c1e90ed6c"}
However, if I make the request through terminal with
curl -XPOST http://localhost:3000/players -d 'name=ronaldo&email=ronaldo#com&score=232'
it works fine.
In addition to this, when try to post or get an Ajax request, I keep getting CORS error even though I added
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');
// 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();
});
I also tried to use cors middleware but no luck.
The server is running at http://92.222.36.106:3000/players for temporarily testing purposes. Feel free to use Postman to post data.
It seems to be working fine. In Postman check that:
Content-Type is set to application/json
body type is set raw and JSON is selected.
Here's some sample data:
{
"name": "Mariano Rajoy",
"email": "sobres.manila#pp.com",
"score": 0
}
If that doesn't work, here's a working example. Save this to a .json file and import it as a collection:
{"id":"d7fd0131-247a-08c0-4c89-5b46712201b8","name":"Players api","timestamp":1425989704352,"requests":[{"collectionId":"d7fd0131-247a-08c0-4c89-5b46712201b8","id":"2c301d19-62e6-6ad5-40bb-0fbec97305be","name":"http://92.222.36.106:3000/players/","description":"","url":"http://92.222.36.106:3000/players/","method":"POST","headers":"Content-Type: application/json\n","data":"{\n \"name\": \"Mariano Rajoy\",\n \"email\": \"sobres.manila#pp.com\",\n \"score\": 0\n}\n","dataMode":"raw","timestamp":0,"responses":[],"version":2}]}
(In your code 'Access-Control-Allow-Origin' is set to 'http://localhost:8888', but i'm assuming you already set it to '*' since i'm using your api with Postman)
EDIT:
Tried with a regular ajax request and it didn't work. Apparently you still have"Access-Control-Allow-Origin" set to "http://localhost:8888" instead of "*" in your code and Postman / Chrome apps can bypass Cross Origin, didn't know that..
set your cross origin request headers properly ,above you are accessing the request from "http://localhost:8888"(set it your domain) .it allows that domain only.Make sure your domain is properly set it or not .
It allows request from any origin
res.setHeader('Access-Control-Allow-Origin', '*');
It allows request from only "http://localhost:8888"
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');

Categories