552

I'm getting this error using ngResource to call a REST API on Amazon Web Services:

XMLHttpRequest cannot load http://server.apiurl.com:8000/s/login?login=facebook. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. Error 405

Service:

socialMarkt.factory('loginService', ['$resource', function ($resource) {
    var apiAddress = "http://server.apiurl.com:8000/s/login/";
    return $resource(apiAddress, {
        login: "facebook",
        access_token: "@access_token",
        facebook_id: "@facebook_id"
    }, {
        getUser: {
            method: 'POST'
        }
    });
}]);

Controller:

[...]
loginService.getUser(JSON.stringify(fbObj)),
    function (data) {
        console.log(data);
    },
    function (result) {
        console.error('Error', result.status);
    }
[...]

I'm using Chrome, and I dont know what else to do in order to fix this problem. I've even configured the server to accept headers from origin localhost.

Hello World
  • 1,089
  • 2
  • 14
  • 39
Andre Mendes
  • 5,807
  • 2
  • 12
  • 22
  • confused: did you "configure the server" or is this "a rest api on amazon web service"? – dandavis Feb 23 '16 at 21:42
  • 3
    You clearly haven't done enough to enable CORS on server side. Post sample of response headers – charlietfl Feb 23 '16 at 21:44
  • 4
    Either way your down votes are wrong. He is hosting his files on his local machine. It won't matter what kind of conf he does on the back end. Angular will not allow this pre flight. – E. Maggini Feb 23 '16 at 21:53
  • @E.Maggini browser doesn't care where server is.... it only knows to make a request...as long as request contains proper headers browser could care less where they come from. Issue has absolutely nothing to do with angular. It's the browser itself that makes the OPTIONS request – charlietfl Feb 23 '16 at 22:09
  • 3
    Thx for the comments, it worked when I set the browser to turn of security – Andre Mendes Feb 24 '16 at 00:12
  • 2
    @Andre But turning off security is just an ugly workaround where you are compromising on security,doesnt solve your problem... – shivi Apr 06 '17 at 06:50
  • with Node JS this https://stackoverflow.com/a/40026625/7822663 link helped me to solve the issue – Poorna Sep 18 '17 at 09:16
  • Please refer to this post for answer nd how to solve this problem https://stackoverflow.com/questions/53528643/cross-origin-resource-sharing-cors-in-angular-or-angular-6-problem-while-you/53528644#53528644 – Ramesh Roddam Nov 28 '18 at 22:11

24 Answers24

286

You are running into CORS issues.

There are several ways to fix/workaround this.

  1. Turn off CORS. For example: how to turn off cors in chrome
  2. Use a plugin for your browser
  3. Use a proxy such as nginx. example of how to set up
  4. Go through the necessary setup for your server. This is more a factor of the web server you have loaded on your EC2 instance (presuming this is what you mean by "Amazon web service"). For your specific server you can refer to the enable CORS website.

More verbosely, you are trying to access api.serverurl.com from localhost. This is the exact definition of cross domain request.

By either turning it off just to get your work done (OK, but poor security for you if you visit other sites and just kicks the can down the road) you can use a proxy which makes your browser think all requests come from local host when really you have local server that then calls the remote server.

so api.serverurl.com might become localhost:8000/api and your local nginx or other proxy will send to the correct destination.


Now by popular demand, 100% more CORS info....same great taste!


Bypassing CORS is exactly what is shown for those simply learning the front end. https://codecraft.tv/courses/angular/http/http-with-promises/

SE_net4 the downvoter
  • 21,043
  • 11
  • 69
  • 107
E. Maggini
  • 7,228
  • 5
  • 23
  • 36
  • I added chrome plugin and it worked for some days. Now it's not working. – Marcel Jan 19 '18 at 12:39
  • @Xvegas You can check here for your server type. https://www.w3.org/wiki/CORS_Enabled – E. Maggini Jul 03 '18 at 15:26
  • 3
    Thank you you saved my day. Used first option only: C:\Program Files (x86)\Google\Chrome\Application>chrome.exe --user-data-dir="C:\Chrome dev session" --disable-web-security. From: https://stackoverflow.com/questions/3102819/disable-same-origin-policy-in-chrome#answer-19317888 – Alwaysalearner Aug 14 '18 at 08:44
  • 9
    Disabling cors in browser? This is not a solution, it's an workaround that doesnt help who really need CORS enabled. – Jonathan Simas Dec 04 '18 at 17:08
  • @JonathanSimas As stated, it is one of several ways to continue with development work. Work-arounds ARE solutions. You'll even note in my answer I say this is poor security and really just kicks the can down the road. ;-) – E. Maggini Dec 04 '18 at 21:37
  • How do we set up the server communication in a dev server/prod server? Please explain .. – Ashfaque Rifaye Feb 13 '19 at 17:30
  • @AshfaqueRifaye That's a separate question you are asking with a very broad answer... – Romeo Sierra May 21 '19 at 10:44
  • you should at least mention that there's a solution which is proper in many cases which is setting CORS. If you do, there will be less to no downvotes anymore – YakovL Sep 19 '19 at 11:03
  • @E.Maggini yeah, but with more meanigful label, I wouldn't guess that "100% more CORS info" is actually about setting CORS on server. I can't suggest edits since I have more than 2K reputation, but if you like, I can edit the post and you may rollback/edit if you don't like some bits. What do you think? – YakovL Sep 19 '19 at 14:56
187

My "API Server" is an PHP Application so to solve this problem I found the below solution to work:

Place the lines in index.php

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
hutchonoid
  • 31,459
  • 14
  • 91
  • 100
Slipstream
  • 9,418
  • 2
  • 47
  • 41
53

In AspNetCore web api, this issue got fixed by adding "Microsoft.AspNetCore.Cors" (ver 1.1.1) and adding the below changes on Startup.cs.

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddCors(options =>
    {
          options.AddPolicy("AllowAllHeaders",
                builder =>
            {
                    builder.AllowAnyOrigin()
                           .AllowAnyHeader()
                           .AllowAnyMethod();
                });
    });
    .
    .
    .
}

and

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{


    // Shows UseCors with named policy.
    app.UseCors("AllowAllHeaders");
    .
    .
    .
}

and putting [EnableCors("AllowAllHeaders")] on the controller.

ArieKanarie
  • 799
  • 10
  • 25
Rajkumar Peter
  • 665
  • 6
  • 4
  • 24
    This is a fine answer if you want to build in cross site scripting vulnerabilities! Please do not ever do this! Specify your domains that you can access to avoid security problems. CORS is there for a reason. – crthompson Jun 20 '17 at 21:29
  • 3
    Just to make it clearer @paqogomez, in your ConfigureServices method: services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", builder => { builder.WithOrigins("http://localhost") .AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod(); }); }); and in your Configure method: app.UseCors("AllowSpecificOrigin"); – Francisco Tena Oct 08 '18 at 10:10
38

There are some caveats when it comes to CORS. First, it does not allow wildcards * but don't hold me on this one I've read it somewhere and I can't find the article now.

If you are making requests from a different domain you need to add the allow origin headers.

 Access-Control-Allow-Origin: www.other.com 

If you are making requests that affect server resources like POST/PUT/PATCH, and if the mime type is different than the following application/x-www-form-urlencoded, multipart/form-data, or text/plain the browser will automatically make a pre-flight OPTIONS request to check with the server if it would allow it.

So your API/server needs to handle these OPTIONS requests accordingly, you need to respond with the appropriate access control headers and the http response status code needs to be 200.

The headers should be something like this, adjust them for your needs:

   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

The max-age header is important, in my case, it wouldn't work without it, I guess the browser needs the info for how long the "access rights" are valid.

In addition, if you are making e.g. a POST request with application/json mime from a different domain you also need to add the previously mentioned allow origin header, so it would look like this:

   Access-Control-Allow-Origin: www.other.com 
   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

When the pre-flight succeeds and gets all the needed info your actual request will be made.

Generally speaking, whatever Access-Control headers are requested in the initial or pre-flight request, should be given in the response in order for it to work.

There is a good example in the MDN docs here on this link, and you should also check out this SO post

Sasa Blagojevic
  • 1,692
  • 13
  • 20
  • 1
    Here is the Mozilla article talking about how you can't use wildcard for cors origin: [Link](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Credentialed_requests_and_wildcards) So apparently this only applies when using credentials (if I'm understanding correctly) – Post Impatica Jun 21 '19 at 17:56
  • I'm using wildcard and submitting a bearer token to authorize the request and it's working fine so not sure what the link I provided above is referring to regarding credentials. My issue was that when bulding my CORS policy in .Net Core I didn't add `.AllowCredentials()`. After adding `.AllowCredentials()` everything worked. – Post Impatica Jun 24 '19 at 16:06
15

JavaScript XMLHttpRequest and Fetch follow the same-origin policy. So, a web application using XMLHttpRequest or Fetch could only make HTTP requests to its own domain.

Source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

You have to send the Access-Control-Allow-Origin: * HTTP header from your server side.

If you are using Apache as your HTTP server then you can add it to your Apache configuration file like this:

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
</IfModule>

Mod_headers is enabled by default in Apache, however, you may want to ensure it's enabled by running:

 a2enmod headers
Tadej
  • 5,099
  • 4
  • 42
  • 57
15

If you're writing a chrome-extension

You have to add in the manifest.json the permissions for your domain(s).

"permissions": [
   "http://example.com/*",
   "https://example.com/*",
   "http://www.example.com/*",
   "https://www.example.com/*"
]
freedev
  • 17,230
  • 4
  • 83
  • 98
9

If you are using IIS server by chance. you can set below headers in the HTTP request headers option.

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';

with this all post, get etc., will work fine.

Sunil Kumar
  • 581
  • 5
  • 14
9

To fix cross-origin-requests issues in a Node JS application:

npm i cors

And simply add the lines below to the app.js

let cors = require('cors')
app.use(cors())
Lucio
  • 3,428
  • 3
  • 37
  • 67
Rohit Parte
  • 1,568
  • 18
  • 13
8

In PHP you can add the headers:

<?php
header ("Access-Control-Allow-Origin: *");
header ("Access-Control-Expose-Headers: Content-Length, X-JSON");
header ("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header ("Access-Control-Allow-Headers: *");
...
atiruz
  • 2,461
  • 22
  • 34
5

For python flask server, you can use the flask-cors plugin to enable cross domain requests.

See : https://flask-cors.readthedocs.io/en/latest/

Teriblus
  • 699
  • 6
  • 15
5

Our team occasionally sees this using Vue, axios and a C# WebApi. Adding a route attribute on the endpoint you're trying to hit fixes it for us.

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }
w00ngy
  • 1,228
  • 15
  • 22
3

In my Apache VirtualHost config file, I have added following lines :

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
hugsbrugs
  • 3,073
  • 2
  • 24
  • 33
3

For those are using Lambda Integrated Proxy with API Gateway. You need configure your lambda function as if you are submitting your requests to it directly, meaning the function should set up the response headers properly. (If you are using custom lambda functions, this will be handled by the API Gateway.)

//In your lambda's index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                "Access-Control-Allow-Origin" : "*"
           }
     }
}
Xu Chen
  • 347
  • 2
  • 8
  • 1
    I want to also chime in and mention one big gotcha I dont think AWS documents. Say you use API gateway to proxy your lambda function, and you use some API in that lambda function. If that API returns a non-200 success success code and you didn't add the non-200 success code into the method response in API gateway then you *will receive an error and not see your successful response*. Examples for this: Sendgrid and Twilio have non-200 success codes. – Stephen Tetreault Aug 01 '18 at 20:29
3

I think disabling CORS from Chrome is not good way, because if you are using it in ionic, certainly in Mobile Build the Issue will raise Again.

So better to Fix in your Backend.

First of all In header, you need to set-

  • header('Access-Control-Allow-Origin: *');
  • header('Header set Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"');

And if API is behaving as GET and POST both then also Set in your header-

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) header("Access-Control-Allow-Headers:
{$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); exit(0); }

2

A very common cause of this error could be that the host API had mapped the request to a http method (e.g. PUT) and the API client is calling the API using a different http method (e.g. POST or GET)

2

For anyone using Api Gateway's HTTP API and the proxy route ANY /{proxy+}

You will need to explicitly define your route methods in order for CORS to work.

enter image description here

Wish this was more explicit in the AWS Docs for Configuring CORS for an HTTP API

Was on a 2 hour call with AWS Support and they looped in one of their senior HTTP API developers, who made this recommendation.

Hopefully this post can save some time and effort for those who are working with Api Gateway HTTP API.

TrieuNomad
  • 1,187
  • 13
  • 19
1

I have faced with this problem when DNS server was set to 8.8.8.8 (google's). Actually, the problem was in router, my application tried to connect with server through the google, not locally (for my particular case). I have removed 8.8.8.8 and this solved the issue. I know that this issues solved by CORS settings, but maybe someone will have the same trouble as me

Kirill Husiatyn
  • 750
  • 2
  • 9
  • 19
1

I am using AWS sdk for uploads, after spending some time searching online i stumbled upon this thread. thanks to @lsimoneau 45581857 it turns out the exact same thing was happening. I simply pointed my request Url to the region on my bucket by attaching the region option and it worked.

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });
davyCode
  • 185
  • 1
  • 4
0

The standalone distributions of GeoServer include the Jetty application server. Enable Cross-Origin Resource Sharing (CORS) to allow JavaScript applications outside of your own domain to use GeoServer.

Uncomment the following <filter> and <filter-mapping> from webapps/geoserver/WEB-INF/web.xml:

<web-app>
  <filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>cross-origin</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
Mr Lister
  • 42,557
  • 14
  • 95
  • 136
0

It's easy to solve this issue just with few steps easily,without worrying about anything. Kindly,Follow the steps to solve it .

  1. open (https://www.npmjs.com/package/cors#enabling-cors-pre-flight)
  2. go to installation and copy the command npm install cors to install via node terminal
  3. go to Simple Usage (Enable All CORS Requests) by scrolling.then copy and paste the complete declartion in ur project and run it...that will work for sure.. copy the comment code and paste in ur app.js or any other project and give a try ..this will work.this will unlock every cross origin resource sharing..so we can switch between serves for your use
Rahul sah
  • 11
  • 1
  • 1
    var express = require('express') var cors = require('cors') var app = express() app.use(cors()) app.get('/products/:id', function (req, res, next) { res.json({msg: 'This is CORS-enabled for all origins!'}) }) app.listen(80, function () { console.log('CORS-enabled web server listening on port 80') }) – Rahul sah Nov 10 '19 at 19:38
  • In my opinion this is also only valid in express node apps but not any others. – Kube Kubow Aug 27 '20 at 05:42
0

enter image description here

Using the Cors option in the API gateway, I used the following settings shown above

Also, note, that your function must return a HTTP status 200 in response to an OPTIONS request, or else CORS will also fail.

Fiach Reid
  • 3,518
  • 1
  • 23
  • 29
-1

Something that is very easy to miss...

IN solution explorer, right-click api-project. In properties window set 'Anonymous Authentication' to Enabled !!!

Wes
  • 11
  • 2
-3

Please restart your chrome/web browser and check the API request again. It worked for me.

-11

Disable the chrome security.Create a chrome shortcut right click -> properties -> target, paste this "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="c:/chromedev"

Nithin
  • 1