I've successfully deployed my Express API app to AWS elastic beanstalk. I have a React front end that is hosted on S3.
Both are on the same domain with the front end being at example.com & the API at api.example.com
Both have certificates and are secured.
const express = require('express');
const cors = require('cors')({
Origin: 'https://example.com'
});
// followed by required middleware
app.use(cors());
//followed by app constants
app.use((e, req, res, next) => {
res.header("Access-Control-Allow-Origin", "https://example.com");
res.header('Access-Control-Allow-Methods', 'DELETE, PUT, GET, POST');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
if (e) {
console.log(e);
res.status(500).send(e.message);
}
next();
})
// followed by app routes
When I try and register a user on my site, I get the error:
Access to XMLHttpRequest at 'https://api.example.com/users/signup/' from origin 'https://example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This topic has of course been covered multiple times on Stack Overflow (which I've gone through multiple solutions this morning), but my question has to do with the actual server where the API is being hosted.
In the hosted zone for api.example.com, it has a TTL of 172800(48 hours). Does this mean that my changes won't be reflected in that time? If that is the case, does this mean that every time you deploy code it resets the TTL?
I'm a front end dev working on a side project, so this really isn't my area of expertise. Any DevOps or BackEnd Devs have any ideas? Thanks in advance!
In the hosted zone for api.example.com, it has a TTL of 172800(48 hours). Does this mean that my changes won't be reflected in that time? If that is the case, does this mean that every time you deploy code it resets the TTL?
No.
The TTL is how long other DNS servers are expected to cache the DNS information (e.g. which server the domain name points to).
It has nothing to do with deployment of code.
Your problem is unrelated to that. I'd add some logging to the server-side code to see which routes and middleware were actually hit as well as monitoring the precise request and response you are getting in the Network tab of your browser.
There a preflight OPTIONS request can be made by the browser for the particular types of cross-domain requests. If the response on that request is not successful or doesn't have CORS headers you will also get such error.
So I suppose that you should add a route in your Express app to handle preflight requests and send back the same CORS headers or just use express-cors-middleware.
Related
I'm currently on a serverless application and my serverless.yml looks like
functions:
app:
handler: server.run
events:
- http:
path: /api/{any+}
method: ANY
- http:
path: /secure/api/{any+}
method: ANY
cors :
origins
- domain-url-1
- domain-url-2
As you can see above one is a secured route and that requires authorization whereas the non-secure route doesn't require any authorization headers to be passed. Since lambda-proxy doesn't take api gateway response I'm attaching the response headers on my app.js as below and for every route I'm sending the status and status codes separately in res objects.
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "*");
res.header("Access-Control-Request-Headers", "*");
// res.headersSent("Access-Control-Allow-Headers", "Content-Type");
res.header('Access-Control-Allow-Headers', "Origin, X-Requested-With, Content-Type, Accept, Authorization, accesstoken");
res.header('Access-Control-Allow-Credentials', true);
next();
});
But my api gateway works fine for non-secure routes while for secure routes I'm getting a CORS issue with
** Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
polyfills.ff5fcb5319b1dc651f7b.js:1 GET https://8nv8r4ph65.execute-api.us-east-1.amazonaws.com/staging/secure/api/v1/legal/notification/list?rowsPerPage=15 net::ERR_FAILED **
I'm not sure where I'm going wrong.
Your origin header does not match specified domains in ApiGateway. For fast verification remove specified domains in serverless.
This is because your secured routes are using one of the methods to pass authentication status that the browser detects as being a request with credentials. Some of the ways a browser marks a request as credentialed is if the request sends back a cookie or if the request includes the Authorization header.
Credentialed requests have an additional rule regarding CORS. The origin * is illegal for credentialed requests. Browser manufacturers instead want server admin/backend developers to tell the browser exactly what domain name is valid for the CORS request.
In addition to the rule above, list of domain names are also illegal for credentialed requests. A request with credentials can only accept one domain for CORS.
You can of course hardcode the domain name of your frontend in your server code. But this gets annoying and is not flexible in case you need to serve multiple domains.
The correct working solution for this scenario (indeed, the way CORS was intended to be used) is to check the Origin header in the request.
The laziest way to make it work is to simply copy the Origin header to Access-Control-Allow-Origin:
res.header("Access-Control-Allow-Origin", req.get("Origin"));
This will allow anyone in the world from any website to access your data. This is perfectly fine if you are OK with this and only care about using authentication to protect your data instead of also using the CORS mechanism.
If you are using the cors middleware you it will do this for you if you pass true as origin:
app.use(cors({ origin: true }));
The way CORS is intended to be used is to check the Origin against a list of approved domains:
const approvedDomains = [
"https://www.google.com",
"https://my.application.com",
"http://my.application.com" // etc..
]
function checkDomains(origin) {
return approvedDomains.filter(domain => domain === origin)[0];
}
res.header("Access-Control-Allow-Origin", checkDomains(req.get("Origin")));
Again, the cors middleware makes this simple allowing you to pass an array of approved domain names and it will do the above logic for you:
app.use(cors({ origin: approvedDomains });
Getting this error "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource ..."
But I had been developing from my localhost:* just hours before. I did nothing to the application settings or CORS settings. Now I have a wildcard and it still doesn't work (above error).
I checked out {app}.scm.azurewebsites.net/Env.cshtml and I see:
...
APPSETTING_WEBSITE_CORS_SUPPORT_CREDENTIALS = True
...
WEBSITE_CORS_SUPPORT_CREDENTIALS=False
...
I don't know if these environment variables are correct or if they changed since my functions were actually working.
While I've found a solution, it probably makes sense to address this problem anyhow.
const proxy = require('express-http-proxy');
const app = require('express')();
const subdomain = '';
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:1234');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.use('/', proxy(`https://${subdomain}.azurewebsites.net`));
app.listen('9091', () => {
console.log('Proxy on http://localhost:9091')
})
Then just pass in proxyUrl as a parameter if you want to preconfigure HATEOAS links.
I think that Azure App Service CORS is taking precedence over your application CORS settings. Quoting from another reply "If you enable one origin domain in App Service, and enable all domains in your Web API code your Azure API app will only accept calls from the domain you specified in Azure".
Here is the link to the other thread: Enable Access-Control-Allow-Credentials header in Azure website (Azure App Services)
I hope that you find this answer helpful :)
This question already has answers here:
No 'Access-Control-Allow-Origin' header with Microsoft Online Auth
(2 answers)
Enable CORS for Azure Rest webapi application
(2 answers)
Enabling CORS on Azure Active Directory
(1 answer)
OAuth2 Access origin error
(2 answers)
“No 'Access-Control-Allow-Origin' header is present” for redirected request to https://login.microsoftonline.com/
(3 answers)
Closed 3 years ago.
Edit: Yes, I've tried all the possible solutions suggested in other threads here. None of them seem to work for me. So before marking this question as duplicate, please look into my explanation. Thanks.
Also, I'm using adal-node npm module for Azure AD Authentication.
I'm trying to resolve the CORS error thrown by my webapp hosted on Azure.
I've my frontend written in Angular 6 (runs on Apache Tomcat server) and have hosted it as an App Service on Azure and I've my backend written in Node.Js (runs o Node server) which is again hosted as another App Service in Azure. My Node.Js code calls some APIs from Netsuite and modifies the data as needed and sends back to Angular frontend.
So when the user first hits the dashboard URL of frontend (xxxx.azurewebsites.net/login), there's a minimal login button, on hitting which an API in my Node.Js backend will be called and here my authentication with the Azure Active Directory takes place. On successful login, the user has to be redirected to dashboard screen of frontend. But here, I'm being thrown this error:
Access to XMLHttpRequest at 'https://login.microsoftonline.com/...redirect_uri=https://xxxxx.azurewebsites.net/forecastSummary...' from 'https://yyyyy.azurewebsites.net/') from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header present on the requested resource.
I've already added the headers in my Node.Js backend as shown below:
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Authorization, Content-Type, Accept');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
next();
});
Plus, I also separately tried enabling CORS setting available in the Azure App Service by using the wildcard '*'. Neither does that seem to be working.
P.S: I can't attach screenshots or pictures supporting the problem since my SO reputation is low.
The Azure CORS settings doesn't seem to work at all unless I specify * any and all requests will return
"has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
I've added my CORS http + https variants of both my production + dev environment frontend. I have also added them in the web.config.
<add name="Access-Control-Allow-Origin" value="https://LINK"/>
<add name="Access-Control-Allow-Origin" value="https://LINK/"/>
It is becoming extremely unpredictable and unreliable. The application is configured to allow all origins:
app.options('/', function(req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', '*');
res.setHeader('Access-Control-Allow-Headers', '*');
res.end();
});
So it would send preflight data. Does azure CORS not send any preflight data? Am I better off just setting * everywhere and then managing things via the API myself? Will Azure not overwrite that configuration anyway? Am I stuck with no way of managing CORS?
Yes, definitely you can achieve it either by setting CORS headers from the Azure portal or by adding CORS headers from your App.
Here's how you can set it form azure portal.
Navigate to azure portal
Navigate to the app service you have created.
Click on CORS in the app.
Enter URL's in the empty Allowed Origins text box.
Click Save.
I'm building a simple web application which has to Cross Origin Resource Sharing restricted to some sites. The app is running in the Azure cloud on an App Service. Right now I have set the CORS headers from both the Azure portal and the Express server app as a middleware in the following way:
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();
});
My question is, that can I remove the CORS headers from the Express App and use only the headers which are provided by the Azure App Service? Thanks.
Yes, definitely you can achieve it either by setting CORS headers from the Azure portal or by adding CORS headers from your App.
For other people’s convenience, here I also provide the following steps to set CORS header from the Azure portal.
Navigate to the Azure portal.
Navigate to your App Service.
Click CORS in the API menu.
Enter each URL in the empty ALLOWED ORIGINS text box. A new text box is created.
Click Save.
They don't recommend to use both