AngularJS NodeJS Cors Issues behind Firewall - node.js

I have a AngularJS and NodeJS (API) application.
I had already enabled CORS on my NodeJS using CORS() nodejs library.
I included the required headers to enable CORS too.
I am having CORS issue only when I access the website from my company computer. It Works fine from my personal computers. Can anyone please guide me on what I am doing wrong. Any help or suggestion please.
Chrome Console Logs:
-------------------- Headers ---------------------
General:
Request URL:www.example.com:81/api/getdata
Request Method:GET
Status Code:503 Service Unavailable
Remote Address:111.111.11.111:81
Response Headers:
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection:close
Content-Length:973
Content-Type:text/html; charset=UTF-8
Expires:Thu, 01 Jan 1970 00:00:00 GMT
P3P:CP="CAO PSA OUR"
Pragma:no-cache
Request Headers:
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:www.example.com:81
Origin:http://www.example.com
Referer:http://www.example.com/
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
-------------------- Response: --------------------
<html>
<head>
<title>Web Page Blocked</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
<meta name="viewport" content="initial-scale=1.0">
</head>
<body bgcolor="#e7e8e9">
<div id="content">
<h1>Web Page Blocked</h1>
<p>Access to the web page you were trying to visit has been blocked in accordance with company policy. Please contact your
system administrator if you believe this is in error.</p>
<p><b>User:</b> </p>
<p><b>URL:</b> www.example.com:81/api/getdata </p>
<p><b>Category:</b> unknown </p>
</div>
</body>
</html>
Browser Console Error:
XMLHttpRequest cannot load http://www.example.com:81/api/getdata. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://www.example.com' is therefore not allowed
access. The response had HTTP status code 503.
------ EDIT -----
Here is the cors() I am passing.
app.options('*',cors());
app.use(function (req, res, next){
res.header("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With,Content-type, Accept");
res.header("Access-Control-Allow-Credentials", true);
next();
});

It's either a problem with your company firewall or a CORS problem.
Try to accept every origin in CORS module :
var express = require('express');
var cors = require('cors')
var app = express();
var corsOptions = {
origin: '*',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
};
app.get('/products/:id', cors(corsOptions), function(req, res, next){
res.json({msg: 'This is CORS-enabled for every origin.'});
});
app.listen(80, function(){
console.log('CORS-enabled web server listening on port 80');
});
Now you should receive response headers like this :
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json
If it still does not work, then port 81 must be blocked.
Another possibility is that the proxy of your company removes or blocks some headers which could explain why Access-Control-Allow-Origin: www.example.com is not present in your response headers

Related

Express/Nodejs received undefined json from angular using post method

What I've done: I tried to post json from angular to nodejs but it failed. I tried to search for solution of "undefined post nodejs json" and "options instead of post", and changed my header to exclude the [option], also tried to parse the json data I tried to set, but nothing is useful.
The problem: In the angular code below, I did not get response, there was no output of the "console.log()", I wonder what is wrong. And the json.body I reuqired in app.js returns "undefined"
I checked the browser, first it sends [options] request and gets 200OK, but next when it sends [post], but no status is returned :
OPTIONS /api/postData HTTP/1.1
Host: 127.0.0.1:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Referer: http://127.0.0.1:4200/
Origin: http://127.0.0.1:4200
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
POST http://127.0.0.1:3000/api/postData
Host: 127.0.0.1:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 27
Origin: http://127.0.0.1:4200
Connection: keep-alive
Referer: http://127.0.0.1:4200/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
Is there any mistake in the code?
angular code: component.ts
this.http.post<any>("http://127.0.0.1:3000/api/postData", loc_json).subscribe(response =>{
console.log("Post to nodejs from angular")
console.log(response);
});
nodejs using express: app.js
const express = require('express')
const api_helper = require('./API_helper')
const port = 3000
const cors = require('cors')
const app = express()
app.use(cors())
// allowCrossDomain = function(req, res, next) {
// res.header('Access-Control-Allow-Origin', '*');
// res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
// res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
// if ('OPTIONS' === req.method) {
// res.send(200);
// } else {
// next();
// }
// };
// app.use(allowCrossDomain);
app.get('/', (req, res, next) => {
res.send("wtffffffffffffffffff");//send to the page
})
app.post('/getAPIResponse', (req, res, next) => {
api_helper.make_API_call('https://jsonplaceholder.typicode.com/posts')
.then(response => {
res.json(response)
})
.catch(error => {
res.send(error)
})
})
//angular --> nodejs
app.post('/api/postData', function(request, response){
//console.log("postData on nodejs 3000");
// const loc_nodejs = req.body;
// console.log("loc_nodejs.loc ", loc_nodejs);
console.log(request.body);
})
app.listen(port, () => console.log(`NodeJS App listening on port ${port}!`))
Because you are using Sec-Fetch-Mode: cors in your request, then your API in Express needs to have CORS enabled and configured correctly. If you are doing local development, I would turn CORS off and enable it in production, but you also may be running two processes for the Angular app and the Express app. In that case, follow the documentation for Express to enable CORS on the API via the documentation below.
https://expressjs.com/en/resources/middleware/cors.html
I added these in my code and they appeared deprecated in the pic, but it does work
const bp = require('body-parser');
app.use(bp.json())
app.use(bp.urlencoded({ extended: true }))\

CORS is enabling for login and next api and failing for all other APIs

I am implementing a React application and node server as a backend. Recently I have updated my chrome version. And also updated some APIs but I haven't done any changes regarding CORS. But from Yesterday login request and the next request is getting success (I mean requests on the load of the application) after that any request that is fired due to event in the browser is failing.
All requests on load of the applications is a success when I go to any other routes by clicking on link API calls in that route Component are failing. I don't understand the reason for getting success on load and getting CORS error on any event-based API request?
My options req/res headers are
Request:
Request URL: http://localhost:4000/apps
Request Method: OPTIONS
Status Code: 204 No Content
Remote Address: [::1]:4000
Referrer Policy: no-referrer-when-downgrade
Res Headers:
Access-Control-Allow-Headers: authorization,orgid
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 0
Date: Sun, 02 Aug 2020 06:58:37 GMT
Strict-Transport-Security: max-age=15552000; includeSubDomains
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Req Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: authorization,orgid
Access-Control-Request-Method: GET
Connection: keep-alive
Host: localhost:4000
Origin: http://localhost:3000
Referer: http://localhost:3000/apps/list
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 Edg/84.0.522.52
This request is always getting success.
But I have another request (this req is failing with CORS)
Req:
Request URL: http://localhost:4000/rs
Request Method: OPTIONS
Status Code: 204 No Content
Remote Address: [::1]:4000
Referrer Policy: no-referrer-when-downgrade
res Headers"
Access-Control-Allow-Headers: appid,authorization
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 0
Date: Sun, 02 Aug 2020 06:59:21 GMT
Strict-Transport-Security: max-age=15552000; includeSubDomains
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Req Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: appid,authorization
Access-Control-Request-Method: GET
Connection: keep-alive
Host: localhost:4000
Origin: http://localhost:3000
Referer: http://localhost:3000/apps/rs/list
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 Edg/84.0.522.52
I have enabled CORS in node API like,
let cors = require('cors')
app.use(cors());
app.use(function (req, res, next) {
next();
});
//routes start from here
Error message:
Access to fetch at 'http://localhost:4000/rs' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Failed GET request headers,
Request URL: http://localhost:4000/rs
Referrer Policy: no-referrer-when-downgrade
res Headers:
Connection: close
req Headers:
Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,te;q=0.8
Authorization: Bearer eyJpZCI6IjVkNTE5NjFlNWMzMDM1NDlkNDYwZjk
Connection: keep-alive
Content-Type: application/json
Host: localhost:4000
orgId: 5dca073d4b044330e44e7946
Origin: http://localhost:3001
Referer: http://localhost:3001/apps/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*"); // "*" means allow connection from any request url.
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
You can change the * with the allowed url.
Or try this cors tutorial make sure to whitelist your request url. In your case 'http://localhost:3000'
// Set up a whitelist and check against it:
var whitelist = ['http://localhost:3000']
var corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
// Then pass them to cors:
app.use(cors(corsOptions));
You don't require all that to send an http request. This is a basic example.
It should be like this:
Server.js
const express = require('express');
const cors = require('cors');
var app = express();
app.use(cors());
app.get('/', function(req, res) {
res.json({'Hello':'World'});
});
app.listen(3000);
Client..html
<html>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$.get("http://localhost:3000/", function(response) {
console.log(resposne);
});
</script>
</html>

CORS problems on node.js

I have a web app with a Node.js backend and Angular front end, both on the same server (Windows Server 2016), however, using different domains. So the front-end is at http://frontend.mydomain.com and the backend is at http://backend.mydomain.com.
Unfortunately I didn't write this web app, nor do I have any experience with Node.js or Angular.
The web app was working perfectly on the older server. However, we have moved both the front-end and the back-end to a new web server, and now, when trying to load it, I get this error message:
/#/login:1 Access to XMLHttpRequest at 'http://backend.mydomain/authenticate' from origin 'http://frontend.mydomain.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Now I'm looking at the server.js file in the backend folder, and this is what it looks like:
var express = require('express');
const sql = require("mssql");
// var cors = require("cors");
var app = express();
var port = process.env.PORT || 3000;
// app.use(cors());
var config =
{
server: "**************",
database: "**************",
user: "**************",
password: "**************",
port: 1433,
connectionTimeout: 1500,
requestTimeout: 1500
};
app.use(function(req, res, next)
{
var data = '';
req.setEncoding('utf8');
req.on('data', function(chunk)
{
data += chunk;
});
req.on('end', function()
{
req.body = data;
next();
});
});
var cors = require("cors"); and app.use(cors()); where commented out, so I tried uncommenting it (and restarting the web service in IIS) but it made no difference.
I did some research, and tried adding things such as
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();
}
as well as a myriad of other things, always remembering to restart the web service in IIS after each change, but nothing I do seems to make a difference. Any suggestions anyone please? Thanks...
EDIT:
So the welcome/login page loads. But as soon as I type in my username and password, and hit the Submit button, I get the error described above. Looking at Developer Tools -> Network, I see that "authenticate" is in red, and when I click on it, it shows this:
Request URL: http://backend.mydomain.com/authenticate
Referrer Policy: no-referrer-when-downgrade
Content-Length: 1208
Content-Type: text/html
Date: Mon, 30 Mar 2020 10:53:26 GMT
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,es-AR;q=0.8,es;q=0.7
Connection: keep-alive
Content-Length: 34
content-type: text/plain
Host: backend.mydomain.com
Origin: http://frontend.mydomain.com
Referer: http://frontend.mydomain.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
myusername!##$%&mypassword
p.s. i have changed actual domain names, usernames and passwords...
It may happen sometimes when the origin didn't implemented correctly, you can setup the back-end for this situation:
Use cors npm (in nodejs back-end) for setup the allowed origin by yourself:
const cors = require("cors");
app.use(cors({
origin: //Hardcoded string of your coming request path or regex for filter anything,
//Like this: "http://frontend.mydomain.com" or /frontend.mydomain.com/
credentials: true //Allow the server to get cookies and other auth data from other
// domains and ports to send cookies
}));
This is worked for me but in some cases you may get in trouble with preflight requests which are some kind of issue that the origin (a path which request is coming from) is not implemented correctly, You have to set a Express middleware for set some header manually (Like yourself):
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://frontend.mydomain.com");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
next();
});
You have to put this all together like this:
const cors = require("cors");
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://frontend.mydomain.com");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
next();
});
app.use(cors({
origin: //Hardcoded string of your coming request path or regex for check in string,
//Like this: "http://frontend.mydomain.com" or /frontend.mydomain.com/
credentials: true //Allow the server to get cookies and other auth data from other
// domains and ports
}));
In res.header("Access-Control-Allow-Origin", "http://frontend.mydomain.com") it's better that you put a specific domain for the origin instead of a "*" because it may be not secure at all. When you put "*" CORS policy would prevent the credentials to be passed.
Hope this works.
I would check in your browser (use the developer tools, go to Network) and ensure you're seeing requests successfully returning allowed methods, headers etc.
You should see headers like:
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: *
If these headers are not being send back, something is going wrong with the CORS setup.
You should at the very least receive an Access-Control-Allow-Origin header.
It may be that something is swallowing the headers you are sending back (such as a proxy). In this case the calls will fail.
Try adding the allowed http methods in your app.use()-
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
next();
}

CORS - OPTIONS ... 404 (not found)

Hi I'm having a problem with CORS.
GENERAL STRUCTURE:
Angular 4 sends data of a Form to my api.
Function saveForm() is executed when I send information about form contact.
app.component.ts
saveForm() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let requestOptions = new RequestOptions({ headers: headers });
// Encode JSON as string to exchange data to web server.
this.data = JSON.stringify(this.myContact);
this.http.post('https://pablocordovaupdated.herokuapp.com/api', this.data, requestOptions).subscribe(res => {
let result = res.json();
if(result['result'] == 'success') {
this.successMessage = true;
}
}
);
}
Here is the root of problem, because I'm using POST and Content-Type->application/json to send my data and by definition It gives me a problem with CORS - preflighted request, here more definition: Link about preflighted request
This meaning that before angular 4 sends the data to the server, this asks to server if it is available to receive my data with the verb OPTION, if the response of server is OK then angular 4 sends the data of form.
PROBLEM:
In console I always get this error message:
OPTIONS https://pablocordovaupdated.herokuapp.com/api 404 (Not Found)
XMLHttpRequest cannot load
https://pablocordovaupdated.herokuapp.com/api. Response to preflight
request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://pablocordova.herokuapp.com' is therefore not
allowed access. The response had HTTP status code 404.
XHR failed loading: POST
"https://pablocordovaupdated.herokuapp.com/api".
ERROR Response {_body: ProgressEvent, status: 0, ok: false,
statusText: "", headers: Headers…}
WHAT I TRIED:
so far, I understand that problem is because https://pablocordovaupdated.herokuapp.com/api doesn't return answer for verb OPTIONS
then I tried to resolve this of 2 ways:
Using cors package CORS package
I configured according documentation.
var express = require('express');
var cors = require('cors');
...
var app = express();
...
app.options('/api', cors());
app.post('/api', cors(), function(req, res, next) {
// Proccess to send this data via email
// and also save in data base(only for learning)
});
But I get in console the same error.
Configuring headers manually by Discussion StackOverFlow or Discussion Github
That code is inserted inside every route that I want to write the headers, in my case:
app.post('/api', function(req, res, next) {
if (req.method === 'OPTIONS') {
console.log('!OPTIONS');
var headers = {};
// IE8 does not allow domains to be specified, just the *
// headers["Access-Control-Allow-Origin"] = req.headers.origin;
headers["Access-Control-Allow-Origin"] = "*";
headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
headers["Access-Control-Allow-Credentials"] = false;
headers["Access-Control-Max-Age"] = '86400'; // 24 hours
headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept";
res.writeHead(200, headers);
res.end();
} else {
// Process to send this data via email
// and also save in data base(only for learning)
}
});
Here the problem is that never execute console.log('!OPTIONS');
Here also I tried simply:
app.post('/api', function(req, res, next) {
console.log('!I AM YOUR FATHER');
...
});
but never is printed.
Note: I tried to see this message with heroku logs because the whole page is in Heroku.
But also doing this I get the same error.
MORE INFORMATION:
When the .../api is called, I have this headers
**GENERAL**:
Request URL:https://pablocordovaupdated.herokuapp.com/api
Request Method:OPTIONS
Status Code:404 Not Found
Remote Address:23.21.185.158:443
Referrer Policy:no-referrer-when-downgrade
**RESPONSE HEADERS**:
HTTP/1.1 404 Not Found
Connection: keep-alive
Server: Cowboy
Date: Wed, 10 May 2017 04:14:45 GMT
Content-Length: 494
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache, no-store
**REQUEST HEADERS**:
OPTIONS /api HTTP/1.1
Host: pablocordovaupdated.herokuapp.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: https://pablocordova.herokuapp.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36
Access-Control-Request-Headers: content-type
Accept: */*
Referer: https://pablocordova.herokuapp.com/
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: es-ES,es;q=0.8
QUESTION:
That is my true problem or I am understanding bad? and/or
What can I do to solve that problem? and/or
Any advices?
Thanks.
The problem seems to be: https://pablocordovaupdated.herokuapp.com/api always returns 404:
$ curl -i https://pablocordovaupdated.herokuapp.com/api
HTTP/1.1 404 Not Found
That is, the server isn’t doing anything special/different for the OPTIONS request — instead all requests are just hitting that 404.
app.post('/api', function(req, res, next) {
console.log('!I AM YOUR FATHER');
...
});
I’m not super clear on how Express handles this case, but it may be that must configure it to send some kind of response for that route — not just a console.log on the server side.
When I look at the content of https://pablocordovaupdated.herokuapp.com/api what I see is just a generic Heroku 404 page — so it’s not being served from your app but instead falling back to being served by Heroku. For example, the contents of that 404 page have this:
<iframe src="//www.herokucdn.com/error-pages/no-such-app.html"></iframe>
That is, it appears to be that request for that URL are never getting handled as expected by your app code at all under any circumstances. So it seems like that’s what you need to fix first.

302 redirect after CORS preflight request to nodejs server

I try to build a platform, which consists of 2 separated parts, the backend and the frontend.
The backend is powered by Express.js and Passport.js. It's available via localhost:3000.
The frontend uses Googles polymer-1.0 and is running on localhost:8001.
I want to do all API stuff on my backend. The Ui calls and get data from the backend.
When try to do an iron-ajax request for authorization to my backend route, I'm getting a CORS error:
XMLHttpRequest cannot load http://localhost:3000/auth/facebook.
The request was redirected to 'https://www.facebook.com/v2.2/dialog/oauth?response_type=code&redirect_uri=…%3A3000%2Fauth%2Ffacebook%2Fcallback&scope=email&client_id=0815',
which is disallowed for cross-origin requests that require preflight.
UI snippet:
iron-ajax
id="login"
url=""
method="GET"
headers='{"X-Requested-With": "XMLHttpRequest"}'
handle-as="json"
on-response="hresponse"
debounce-duration="300">
/iron-ajax>
_handleTap: function () {
var url = 'http://localhost:3000/auth/' + this.service;
this.$.login.url = url;
this.$.login.generateRequest();
},
Backend snippet:
app.get('/auth/facebook', passport.authenticate('facebook', { scope: 'email' }));
app.get('/auth/facebook/callback', passport.authenticate('facebook'), function(req, res) {
res.status(200).json({
success: true,
message: 'Enjoy!',
redirect: '/route/to/nowhere',
}).end();
});
As you can see, I'm just using the simple Facebook auth snippet from passport.js documenation.
There were 2 request proceeded:
PREFLIGHT:
RESPONSE
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Allow: GET,HEAD
Content-Type: text/html; charset=utf-8
Content-Length: 8
ETag: W/"8-8ww6QOmj5lyGjHVKXelZGQ"
Date: Tue, 26 Jan 2016 12:59:20 GMT
Connection: keep-alive
REQUEST
OPTIONS /auth/facebook HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:8001
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36
Access-Control-Request-Headers: accept, x-requested-with
Accept: */*
DNT: 1
Referer: http://localhost:8001/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
GET:
RESPONSE
HTTP/1.1 302 Found
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Location: https://www.facebook.com/v2.2/dialog/oauth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Ffacebook%2Fcallback&scope=email&client_id=0815
Content-Length: 0
Date: Tue, 26 Jan 2016 12:59:20 GMT
Connection: keep-alive
REQUEST
GET /auth/facebook HTTP/1.1
Host: localhost:3000
Connection: keep-alive
accept: application/json
Origin: http://localhost:8001
x-requested-with: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36
DNT: 1
Referer: http://localhost:8001/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
My node.js server also accepts CORS requests
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();
});
When using localhost:3000/auth/facebook as a link, I get my json response from the backend and on port 3000, but that is not what I want.
Is there a possibility to handle such API requests via an own API interface, like mine? Currently I see here a big show stopper.
Thanks & BR;
andre
I think the issue has to do with redirection and CORS.
Redirections with the status codes of 301, 302, 303, 307, or 308, will get you an error.
This is being changed, but for now you need a workaround such as sending back the redirect URL in the response header or body, without using a redirect.
This is well explained in this reply
The only way for a user to authenticate with Facebook is if you actually send the user to Facebook. Doing an XMLHttpRequest won't work because there is no way for the user to login to their Facebook account, approve your application, etc. You must actually redirect the user's browser.
Change your _handleTap function to this:
_handleTap: function () {
var url = 'http://localhost:3000/auth/' + this.service;
window.location = url
}
You need to add this middleware to all your request this way
app.all('/*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', req.headers.origin || '*');
res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,HEAD,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'content-Type,x-requested-with');
next();
});
like explained here How to allow CORS in Express/Node.js?
This error basically means, the server is not accepting Cross Origin Requests (Requests from other domains). In express.js you can use a middleware to enable your server to do this.
var cors = require('cors');
app.use(cors());

Resources