I'm working on a small ToDo app where I've Angular as front-end and Node.js/Express/Mongo as middleware/backend.
While I submit Login in my Login form, it hits the login API, however it returns one strange output in the console saying
OPTIONS http://localhost:3000/api/v1/users/login/ 0 {}
(see screenshot below) which doesn't allow me to get the dashboard even after successful login.
I've enabled CORS through installing the cors NPM module. and I've checked RESTFul services in Postman, and all are working fine.
[Updated] This is how I've enabled the CORS in my express.js's app.js file.
let cors = require('cors');
app.use(cors());
app.options('*', cors());
before a CORS request is sent to the server, clients will always send this "OPTIONS" request as a "preflight request", soliciting supported methods from the server.
This request being blocked may be an indicator of a wrong CORS configuration or an explicit block of all "OPTIONS" requests from the server. (CORS needs to be configured on the server as well).
More information can be found here
It seems that this is a known nodejs issue that is still open.
Based on the open github, seems that the best recommendation is to try something like this:
you need to allow both:
// Http.OPTIONS method for request that is hitting " apiUrl =https://127.0.0.1:3000/login".
// Allow CORS like below:
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'content-type');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
Another great idea is to use the angular proxy settings for local development so that you will not need to add CORS for localhost at all.
Very good guidance in this SO answer here on setting up a proxy for angular If this work, then you can make 100% sure that it is indeed a CORS problem.
To handle CORS in express you dont need to add any dependency.
Notice that http://localhost:4200 is you angular app.
This worked for me:
//Add here whatever route you are using for the api.
app.use('/api', (req, res, next) => {
//Where http://localhost:4200 is the angular app
res.header('Access-Control-Allow-Origin', 'http://localhost:4200'),
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
next();
})
Note:
This goes after the place where you import the routes and before where you use them. kind of like:
const apiRouter = require('./app_api/routes/api_routes');
//The code i posted here
app.use('/api', apiRouter);
Related
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.
I have an Angular 5 front end app with a PHP API on separate domains. Most of the time the front end app is requesting data from the API. To enable this, I had to add a CORS Middleware class to the PHP (Laravel) project:
namespace App\Http\Middleware;
use Closure;
class Cors
{
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Headers', 'Authorization, Origin, X-Requested-With, Content-Type, Accept')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
}
}
In a few cases, however, I've needed to generate some HTML through PHP, and I want to request some assets (such as images and fonts) from the Angular app. But when I try this, I get a CORS error. Can you tell me how I can enable CORS requests TO my Angular 5 app?
You can't make a CORS request to the client. The client makes the request. The server makes the response.
If you are getting a CORS related error when a static file is requested, then you need to configure your server to put the appropriate headers in the response.
Since the response isn't handled by PHP, your middleware isn't running. So you'll need to find another approach.
There is plenty of documentation out there on how to configure various servers to set HTTP headers (and plenty which is specific to CORS), so identify which HTTP server you are using and look up how to do it.
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())
How I can deal with the CORS policy in Web Worker?
I would like to make an HTTPS call in a worker, but it throws the following CORS exception:
XMLHttpRequest cannot load xxxx Origin localhost is not allowed by Access-Control-Allow-Origin.
Maybe I should mention that I'm testing it on a Safari browser
I can't comment so I add my 2 cents in "answer".
It looks like you haven't configured the CORS headers, you can follow the great tutorial here:
http://www.html5rocks.com/en/tutorials/cors/
BR,
Saar
With Web Workers, you can inject scripts with importScripts(). If your server supports JSONP, you could directly make a request like this:
importScripts('http://example.com?jsonp=HandleResponse');
function HandleResponse(data) {
// Do something with the data
}
It depends on your web server type. E.g. in Express.js (node.js) you make it so:
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();
});
For other web servers see this site: http://enable-cors.org/server.html
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');