Preflight response is not successful with proper headers - php

I'm having issue getting my ionic app to POST to my API. On my api I have set the following headers:
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Content-Type");
header("Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS");
When posting from Postman or the actual website, everything functions as expected and I see these headers come back but once I open up my app and send a request, it no longer works.
GET Requests are working fine, it's just POST requests that are broken. I use the following to send a post request on my app:
/**
* Post to the API
* #param path Where to go
* #param params What to send
*/
private post(path, params): Promise<any> {
return this.http
.post(this.apiUrl + path, params)
.toPromise()
.then(r => r.json());
}
I get the following error inside of my ionic app
Failed to load resource: Preflight response is not successful
XMLHttpRequest cannot load https://mmcalc.com/api/calculate. Preflight response is not successful
I've been pulling my hair out over this for nearly 15 hours now, I don't understand why it won't work.

This issue happened due to the WKWebView Mostly
So, the very simple way to use the WKWebView in Ionic is that You Must uninstall the previously installed UIWebView from the plugin by running the following command.
ionic cordova plugin remove cordova-plugin-ionic-webview
After that try to add the WKWebView Plugin with this command
ionic cordova plugin add cordova-plugin-wkwebview-engine
When the WkWebView plugin is installed the very next thing is to add the following lines in the config.xml file
feature name="CDVWKWebViewEngine"
param name="ios-package" value="CDVWKWebViewEngine"
feature
preference name="CordovaWebViewEngine" value="CDVWKWebViewEngine"
preference name="WKWebViewOnly" value="true"
After doing all that when you try to run the application and hit some api call you will get the preflight issue in that due to CORS so to fix that. Simply run the following command
ionic cordova plugin add cordova-plugin-wkwebviewxhrfix
After adding the above plugin the CORS issue will be resolved
Thanks,
Happy Coding

If you're only having the issue in iOS then it sounds like an issue with WKWebView
https://ionicframework.com/docs/wkwebview/
When the server receives the OPTIONS request, what does it respond with?
I would make sure the response from the OPTIONS request contains the headers WKWEBView is expecting, otherwise it will prevent the code from the making the call.

The solution was very simple but not very obvious, I simply had to set the proper headers on my API. This article solved the issue for me and was very simple.
# Always set these headers.
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"
# Added a rewrite to respond with a 200 SUCCESS on every OPTIONS request.
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

the preflight request uses the OPTIONS request method. You should make sure that your API endpoint returns a successful status code for the OPTIONS request method and the response should also include the CORS headers which you have mentioned above. GET requests are probably working because they dont need a prefligh request. I would guess that in your case the OPTIONS method returns a wrong status code.

Related

access to xmlhttprequest has been blocked by cors policy no 'access-control-allow-origin' [duplicate]

I am working on an app using Vue js.
According to my setting I need to pass to a variable to my URL when setting change.
<!-- language: lang-js -->
$.get('http://172.16.1.157:8002/firstcolumn/' + c1v + '/' + c1b, function (data) {
// some code...
});
But when my app hit on URL, it shows the following message.
Failed to load http://172.16.1.157:8002/firstcolumn/2017-03-01/2017-10-26: Redirect from 'http://172.16.1.157:8002/firstcolumn/2017-03-01/2017-10-26' to 'http://172.16.1.157:8002/firstcolumn/2017-03-01/2017-10-26/' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
In addition to what awd mentioned about getting the person responsible for the server to reconfigure (an impractical solution for local development) I use a change-origin chrome plugin like this:
Moesif Orign & CORS Changer (use to be free but now wants a work email address >_>)
Allow CORS: Access-Control-Allow-Origin
You can make your local dev server (ex: localhost:8080) to appear to be coming from 172.16.1.157:8002 or any other domain.
In case the 2nd plugin link breaks in the future or the plugin writer decides to capitalize off the fame of this thread, open your browser's
plugin marketplace and search "allow cors", there's going to be a
bunch of them.
Thanks all, I solved by this extension on chrome.
Allow CORS: Access-Control-Allow-Origin
If you have control over your server, you can use PHP:
<?PHP
header('Access-Control-Allow-Origin: *');
?>
Ask the person maintaining the server at http://172.16.1.157:8002/ to add your hostname to Access-Control-Allow-Origin hosts, the server should return a header similar to the following with the response-
Access-Control-Allow-Origin: yourhostname:port
Using npm:
To allow cross-origin requests install 'cors':
npm i cors
Add this in the server-side:
let cors = require("cors");
app.use(cors());
When you have this problem with Chrome, you don't need an Extension.
Start Chrome from the Console:
chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security
Maybe you have to close all Tabs in Chrome and restart it.
I will assume that you're a front-end developer only and that you don't have access to the backend of the application (regarding the tags of the question).
Short answer on how to properly solve this in your case? You can't, you'll need somebody else.
What is this about?
You need to understand that CORS is a security thing, it's not just here to annoy you just for fun.
It's purpose is to mainly prevent the usage of a (malicious) HTTP call from a non-whitelisted frontend to your backend with some critical mutation.
You could give a look to this YouTube video or any other one really, but I recommend a visual video because text-based explanation can be quite hard to understand.
You also need to understand that if you use Postman or any other tool to try your API call, you will not get the CORS issue. The reason being that those tools are not Web frontends but rather some server-based tools.
Hence, don't be surprised if something is working there but not in your Vue app, the context is different.
Now, how to solve this?
Depending of the framework used by your backend team, the syntax may be quite different but overall, you'll need to tell them to provide something like Access-Control-Allow-Origin: http://localhost:3000 (or any other port you'll be using).
PS: Using Access-Control-Allow-Origin: * would be quite risky because it would allow anybody to access it, hence why a stricter rule is recommended.
If you're using a service, like an API to send SMS, payment, some Google console or something else really, you'll need to allow your localhost in the dashboard of the service. Ask for credentials to your manager or Tech Lead.
If you have access to the backend, you could it yourself as shown here (ExpressJS in this example): https://flaviocopes.com/cors/
How to hack it in a dirty way?
If you're in a damn hurry and want to get something really dirty, you could use a lot of various hacks a listed in the other answers, here's a quick list:
use any extension who is able to create a middleware and forward the request to the backend (it will work because it's not directly coming from your frontend)
force your browser to disable CORS, not sure how this would actually solve the issue
use a proxy, if you're using Nuxt2, #nuxtjs/proxy is a popular one but any kind of proxy (even a real backend will do the job)
any other hack related somehow to the 3 listed above...
At the end, solving the CORS issue can be done quite fast and easily. You only need to communicate with your team or find something on your side (if you have access to the backend/admin dashboard of some service).
I heavily do recommend trying get it right from the beginning because it's related to security and that it may be forgotten down the road...
The approved answer to this question is not valid.
You need to set headers on your server-side code
app.use((req,res,next)=>{
res.setHeader('Access-Control-Allow-Origin','*');
res.setHeader('Access-Control-Allow-Methods','GET,POST,PUT,PATCH,DELETE');
res.setHeader('Access-Control-Allow-Methods','Content-Type','Authorization');
next();
})
You can also try a chrome extension to add these headers automatically.
Hello If I understood it right you are doing an XMLHttpRequest to a different domain than your page is on. So the browser is blocking it as it usually allows a request in the same origin for security reasons. You need to do something different when you want to do a cross-domain request. A tutorial about how to achieve that is Using CORS.
When you are using postman they are not restricted by this policy. Quoted from Cross-Origin XMLHttpRequest:
Regular web pages can use the XMLHttpRequest object to send and receive data from remote servers, but they're limited by the same origin policy. Extensions aren't so limited. An extension can talk to remote servers outside of its origin, as long as it first requests cross-origin permissions.
To add the CORS authorization to the header using Apache, simply add the following line inside either the <Directory>, <Location>, <Files> or <VirtualHost> sections of your server config (usually located in a *.conf file, such as httpd.conf or apache.conf), or within a .htaccess file:
Header set Access-Control-Allow-Origin "*"
And then restart apache.
Altering headers requires the use of mod_headers. Mod_headers is enabled by default in Apache, however, you may want to ensure it's enabled.
I had the same problem in my Vue.js and SpringBoot projects. If somebody work with spring you can add this code:
#Bean
public FilterRegistrationBean simpleCorsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// *** URL below needs to match the Vue client URL and port ***
config.setAllowedOrigins(Collections.singletonList("http://localhost:8080"));
config.setAllowedMethods(Collections.singletonList("*"));
config.setAllowedHeaders(Collections.singletonList("*"));
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
I found solution in this article Build a Simple CRUD App with Spring Boot and Vue.js
You are making a request to external domain 172.16.1.157:8002/ from your local development server that is why it is giving cross origin exception.
Either you have to allow headers Access-Control-Allow-Origin:* in both frontend and backend or alternatively use this extension cors header toggle - chrome extension unless you host backend and frontend on the same domain.
Try running this command in your terminal and then test it again.
curl -H "origin: originHost" -v "RequestedResource"
Eg:
If my originHost equals https://localhost:8081/ and my RequestedResource equals https://example.com/
My command would be as below:
curl -H "origin: https://localhost:8081/" -v "https://example.com/"
If you can notice the following line then it should work for you.
< access-control-allow-origin: *
Hope this helps.
Do specify #CrossOrigin(origins = "http://localhost:8081")
in Controller class.
You can solve this temporarily by using the Firefox add-on, CORS Everywhere. Just open Firefox, press Ctrl+Shift+A , search the add-on and add it!
You won't believe this,
Make sure to add "." at the end of the "url"
I got a similar error with this code:
fetch(https://itunes.apple.com/search?term=jack+johnson)
.then( response => {
return response.json();
})
.then(data => {
console.log(data.results);
}).catch(error => console.log('Request failed:', error))
The error I got:
Access to fetch at 'https://itunes.apple.com/search?term=jack+johnson'
from origin 'http://127.0.0.1:5500' 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.
But I realized after a lot of research that the problem was that I did not copy the
right URL address from the iTunes API documentation.
It should have been
https://itunes.apple.com/search?term=jack+johnson.
not
https://itunes.apple.com/search?term=jack+johnson
Notice the dot at the end
There is a huge explanation about why the dot is important quoting issues about DNS and character encoding but the truth is you probably do not care. Try adding the dot it might work for you too.
When I added the "." everything worked like a charm.
I hope it works for you too.
install:
npm i cors
Then include cors():
app.get("/list",cors(),(req,res) =>{
});
In addition to the Berke Kaan Cetinkaya's answer.
If you have control over your server, you can do the following in ExpressJs:
app.use(function(req, res, next) {
// update to match the domain you will make the request from
res.header("Access-Control-Allow-Origin", "YOUR-DOMAIN.TLD");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
https://enable-cors.org/server_expressjs.html
I tried this code,and that works for me.You can see the documentation in this link
var io = require("socket.io")(http, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
})
The reason that I came across this error was that I hadn't updated the path for different environments.
you have to customize security for your browser or allow permission through customizing security. (it is impractical for your local testing)
to know more about please go through the link.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
These errors may be caused due to follow reasons, ensure the following steps are followed. To connect the local host with the local virtual machine(host). Here, I'am connecting http://localhost:3001/ to the http://abc.test Steps to be followed:
1.We have to allow CORS, placing Access-Control-Allow-Origin: in header of request
may not work. Install a google extension which enables a CORS request.*
2.Make sure the credentials you provide in the request are valid.
3.Make sure the vagrant has been provisioned. Try vagrant up --provision this make the localhost connect to db of the homestead.
Try changing the content type of the header. header:{ 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8;application/json' }
this point is very important.
Another solution to this problem in a specific scenario :
If
AWS APIGW is your backend with authentication enabled and
authentication fails,
your browser may end up complaining about CORS even if CORS is enabled in APIGW. You also need to enable CORS for 4XX as follows
API:YourAPI > Resources > /YourResource > Actions > Enable CORS > Gateway Responses for yourAPI check Default 4XX
Authentication will still fail but it won't look like CORS is the root cause
$.get('https://172.16.1.157:8002/firstcolumn/' + c1v + '/' + c1b, function (data) {
// some code...
});
Just put "https" .

Getting error like Response to preflight request doesn't pass access control check

I am doing Laravel project. In this I have folder name as onlinebookingmanager in localhost. And I run a command like npm run dev. After this I run the url http://localhost:8080/admin/login. Now i am getting error like
Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://localhost' that is not equal to the supplied origin. Origin 'http://localhost:8080' is therefore not allowed access.
I have installed plugin CORS but it seems doesn't working.
This issue due to missing header attribute Access-Control-Allow-Origin which should be *.
Best way to resolve this issue is integrate the following library to your laravel project
https://github.com/barryvdh/laravel-cors
This library provides CORS solution in middleware so in every request you will get perfect header.
Have you included following code in your app.js
var cors = require('cors')
var app = express();
app.use(cors());
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();
});
Hope it helps.

Unable to consume this JSON records in angular

In the attached screenshot, I have configured the API in CORS ( drupal ), but still getting the error
10:41:21.021 Cross-Origin Request Blocked: The Same Origin Policy
disallows reading the remote resource at
http://happylife.in/techies/santaws_resources/santaws_resources.json.
(Reason: CORS header 'Access-Control-Allow-Origin' does not match
'http://happylife.in/techies').1
Honestly this is duplicate thread, but I just changed few stuff, here is the API service hosted in public domain, lets try in your code and let me know, you can able to consume this JSON records in your ANGULAR code OR NOT But I can able to read this JSON in PHP program.
http://happylife.in/techies/santaws_resources/santaws_resources.json
api
Due to https://en.wikipedia.org/wiki/Same-origin_policy, an application running in a browser by default cannot fetch (via XHR) a resource from another origin (domain, in your case). PHP doesn't have this limitation. To fetch a resource from another origin, there are various browser-side techniques as well as the option to proxy the fetch through your backend.
This is a CORS issue.
You need to send Access-Control-Allow-Origin header with your response for it to work.
Update for edit1
The error
Access-Control-Allow-Origin' does not match
means that this header doesn't contain the name of your site. Please check if you receive this header in the following format.
Access-Control-Allow-Origin: 'http://www.yoursite.com'
In drupal
step 1 and 2 solved the issue.
step 1
step 2

"Test failed: Error: Origin is not allowed by Access-Control-Allow-Origin" in Composer - Appgyver

I am creating an App in Appgyver Composer.
I have a PHP file which perfect and gives appropriate response when triggered. I tried making this a service by putting appropriate credentials. However, the test returned the following error :
"Test failed: Error: Origin is not allowed by Access-Control-Allow-Origin"
Any idea how I can set Access Control Allow Login to "*" in Composer? The tag already exists in the php file on my server.
I have also added "Access-Control-Allow-Origin" in header to "*", hoping that might do the trick.
Anyone did anything similar?
I used a workaround. The POST method on the server was creating the issue, apparently. I used GET method and it started working perfectly. You might wanna consider that later.
In your php script, set Access-Control-Allow-Origin to the value of the calling domain (the value of the Origin header). If you don't care who has access, you can just send back the Origin header from the request as so:
$origin = $_SERVER['HTTP_ORIGIN'] !== null ? $_SERVER['HTTP_ORIGIN'] : '*';
header('Access-Control-Allow-Origin: '.$origin);
HTTP access control (CORS)
when responding to a credentialed request, server must specify a domain, and cannot use wild carding.

IONIC Content-Type is not allowed by Access-Control-Allow-Headers

I was working on an angularJS, IONIC project with CI backend.
I was sending parameters to the server using POST Method, and receiving it using the CodeIgniter Input class and everything was working OK.
Now that app going to be native Android, the developer should send parameters as JSON array. So I changed my backend API function to receive it like:
$data = json_decode(file_get_contents('php://input'), true);
$email = $data->email;
It works great but the problem now is when I try to access the function using IONIC app I get an php error.
XMLHttpRequest cannot load
http://192.168.1.122/project/index.php/api/login.
Request header field Content-Type is not allowed by Access-Control-Allow-Headers.
on my API I allowed all CORS
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT');
...But I still get the same error.
Can I get any other solution around this point.
Thanks for your help.
You have to add cordova-plugin-whitelist plugin to implements a whitelist policy for navigating the application webview on Cordova 4.0
ionic plugin add cordova-plugin-whitelist
then
ionic build <platform>
Source

Categories