I actually do not understand this issue. I am not very much into SSL and certificates.
A script on test.kanubox.de (You can try it there and look at the source code) uses ajax to call rest server on sandbox.api.kehrwasser.com/kanubox/v1. Obviously CORS is needed and works well without SSL, thus I assume that CORS is set up correctly. The header data on an OPTIONS-request (preflight) to the API confirms
Access-Control-Allow-Origin: *
Upgrade: h2,h2c
Pragma: no-cache
Keep-Alive: timeout=5, max=100
Content-Type: application/json
Content-Encoding: gzip
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT
Server: Apache/2.4
Expires: Fri, 19 Aug 2016 12:15:58 GMT
Access-Control-Max-Age: 500
Access-Control-Allow-Headers: x-requested-with, Content-Type, origin, authorization, accept, client-security-token, Access-Control-Allow-Origin, X-Frame-Options
But when I switch to https://test.kanubox.de and call the API at https://sandbox.api.kehrwasser.com/kanubox/v1 I get CORS error from FireFox like "(Cross-Origin blocked)
Reason: CORS-Header 'Access-Control-Allow-Origin' missing
(Translated error message)
The certificate is from my hoster and verified by my hoster itself. I'm not sure but is it "self-signed" then? So maybe FF blocks it because it doesn't trust it?
Here is my code:
var test = angular.module("test", []);
test.constant('apiConfig', {
apiUrl: "https://sandbox.api.kehrwasser.com/kanubox/v1"
});
test.controller("TestController", function($scope, $http, apiConfig) {
var credentials = { mail: "user#mailserver.com", password: "12345" };
// POST REQUEST VIA SSL
$http({
url: apiConfig.apiUrl + "/users/auth/",
method: 'POST',
data: credentials
}).success(function(data, status, headers, config) {
$scope.variable = data;
}).error(function(data, status, headers, config) {
$scope.variable = data;
});
});
If I browse to https://test.kanubox.de/, then the server certificate is not known in my firefox browser. It is indead a self signed certificated, issued by "Hostpoint DV SSL CA - G2" itself!
To make that SSL certificate work, you need the "Hostpoint" root certificate in your browser. That is exactly how you made it work! So, is was a trusted ROOT certificate issue.
When the SSL problem is solved, then you can look at the CORS issue.
The certificate which is used in https://sandbox.api.kehrwasser.com/kanubox/v1/ is a issued by the well known CA "Let's incrypt". That works fine.
Related
What is my Problem:
I'm making an vue3 app where the login and registration should be done over back4app.
So i initialize the connection as early as possible with the code below:
Parse.initialize(
config.back4app_applicationId,
config.back4app_clientKey
)
Parse.serverURL = config.back4app_url
After this code ran there is a successful health request to the back4app-Servers
And here is the code used for sign Up:
const parseUser = new Parse.User()
parseUser.set("username", userData.username)
parseUser.set("email", userData.email)
parseUser.set("password", userData.password)
try {
await parseUser.signUp()
} catch (error) {
console.error("error: ", error)
}
When the code runs the site is sending an request to the back4app server. Respon below
Response-body:
unauthorized
Response-headers:
access-control-allow-credentials: true
access-control-allow-headers: DNT, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, X-Application-ID, X-Access-Token, X-Parse-Master-Key, X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, X-CSRF-Token, X-Apollo-Tracing, X-Parse-Client-Key, X-Parse-Installation-Id
access-control-allow-methods: GET, HEAD, OPTIONS, POST, PUT, DELETE
access-control-allow-origin: https://localhost:3000
access-control-expose-headers: X-Parse-Job-Status-Id
access-control-max-age: 1728000
content-length: 24
date: Wed, 28 Jul 2021 10:23:10 GMT
server: nginx/1.18.0 (Ubuntu)
via: 1.1 7fcb41b117930690c299be9cec4a977a.cloudfront.net (CloudFront)
x-amz-cf-id: AX6MG8omTAxfGPQUHUR4SkRnWW9gp33_kqJHXgEFv9eIATnI1muxyA==
x-amz-cf-pop: FRA6-C1
x-cache: Error from cloudfront
x-powered-by: Express
What have i tried:
I tried to run the code on a different PC
run the code on a site where the domain has a (not self-signed) HTTPS certificate
giving parse the master key on initiation of my application
different browsers
searching for solution in back4app and parse docs
Changing the public class level permissions for the Userclass
Hopefully i supplied all necessary information for the problem. I'm pretty lost what could be the error here and I'm very grateful for every answer.
The Error was me using the clientkey instead of the javascriptkey.
Thanks to #DaviMacêdo for providing the answer.
im making an api using Javalin and trying to send data to it from javascript, however i get cors errors whenever i try to do so. i can recieve data just fine but not send data. Here is my error: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
-----------javascript-----------
function sendOurAjax(){
console.log("ajax using fetch")
let ourCustomSuper = {
"name": "SpaceMonkey",
"superpower": "person atmosphere",
"bounty": 0
}
fetch(`http://localhost:8000/api`, {
method: "post",
'headers': {
'Content-Type': 'application/json',
'BARNACLES': 'custom header value'
},
'body': JSON.stringify(ourCustomSuper)
})
.then(
function(daResponse){
console.log(daResponse);
const convertedResponse = daResponse.json();
return convertedResponse;
}
).then(
function(daSecondResponse){
console.log("Fetch is a thing. We did it.");
console.log(daSecondResponse);
}
).catch(
(stuff) => {console.log("this sucker exploded")}
)
}
-----------java-----------
app.get("/api", context ->{
context.header("Access-Control-Allow-Origin", "*");
context.header("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
context.header("Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token");
System.out.println("The endpoint method has fired");
context.result("endpoint handler has fired");
context.json(myList);
});
Why was the CORS error there in the first place?
The error stems from a security mechanism that browsers implement called the same-origin policy.
The same-origin policy fights one of the most common cyber attacks out there: cross-site request forgery. In this maneuver, a malicious website attempts to take advantage of the browser’s cookie storage system.
For every HTTP request to a domain, the browser attaches any HTTP cookies associated with that domain. This is especially useful for authentication, and setting sessions. For instance, it’s feasible that you would sign into a web app like facebook-clone.com. In this case, your browser would store a relevant session cookie for the facebook-clone.com domain:
here a link on the cors subject
How To Fix CORS Error
Offhand is see you do have the
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: http://localhost:3000
set but the content type might be wrong i.e json
something along the lines of
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type
Content-Type: application/json
I know there are a ton of similar posts about this subject, but I have been at this almost full time for two days and tried & read about any possible solution i could find. None worked so I am trying to figure out if any other expert has an idea that might work.
I'm trying to call a PHP script on (fictional) websiteshop.net from websitedojo.com. It's done with an AJAX call and works fine on the native URL.
I'm transferring the program, but want to leave the backend scripts on the native/original URL. I'm getting the error that is well known and widely diuscussed:
Failed to load https://websiteshop.net/cl/ajax-tst.php: The
'Access-Control-Allow-Origin' header contains multiple values
'https://websitedojo.com, *', but only one is allowed. Origin
'https://websitedojo.com' is therefore not allowed access.
Plus, after clikcing the alert box:
Cross-Origin Read Blocking (CORB) blocked cross-origin response
https://websiteshop.net/cl/ajax-tst.php with MIME type
application/json. See
https://www.chromestatus.com/feature/5629709824032768 for more
details.
I have tested so many things by now it is driving me insane. Below the part of an AJAX call, I tried all sorts of variations and combinations here. Whatever is commented, I tried as well without comments of course:
AJAX:
$.ajax({
url: "https://websiteshop.net/cl/ajax_tst.php", // Url to which the request is send
// headers:{
// "Access-Control-Allow-Origin": "*"
// },
type: "POST", // Type of request to be send, called as method
data: new FormData(this), // Data sent to server, a set of key/value pairs (i.e. form fields and values)
//data: data,
crossOrigin: true,
dataType: 'jsonp',
contentType: false, // The content type used when sending data to the server.
cache: false, // To unable request pages to be cached
processData: false, // To send DOMDocument or non processed data file it is set to false
success: function (data) // A function to be called if request succeeds
{
...
In htaccess I tried all combinations like these and others:
Options -Indexes
Header set Access-Control-Allow-Origin "https://websitedojo.com, *"
#<IfModule mod_headers.c>
# SetEnvIf Origin "http(s)?://(www\.)?(websitedojo.com|other.nl)$" AccessControlAllowOrigin=$0$1
# Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
# Header set Access-Control-Allow-Credentials true
#</IfModule>
In the PHP file itself, I tried these combinations (also without https://):
header_remove('Access-Control-Allow-Origin');
// header('Access-Control-Allow-Origin: "https://websitedojo.com, *');
$allowed=array('https://websitedojo.com','https://www.websitedojo.com', 'https://websiteshop.net','http://localhost','http://127.0.0.1');
$origin=isset($_SERVER['HTTP_ORIGIN'])?$_SERVER['HTTP_ORIGIN']:$_SERVER['HTTP_HOST'];
if(in_array($origin, $allowed)){
header('Access-Control-Allow-Origin: '.$origin);
}else{
exit(0);
}
header('Access-Control-Allow-Methods: POST, OPTIONS, GET, PUT');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Headers: Authorization, X-Requested-With');
header('P3P: CP="NON DSP LAW CUR ADM DEV TAI PSA PSD HIS OUR DEL IND UNI PUR COM NAV INT DEM CNT STA POL HEA PRE LOC IVD SAM IVA OTC"');
header('Access-Control-Max-Age: 1');
This is the latest result from the headers.
Requestheaders:
Host: websiteshop.net
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept: */*
Accept-Language: nl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br
Referer: https://websitedojo.com/websiteshop/dynamic-and-crazy-engagement/
Content-Type: multipart/form-data; boundary=---------------------------23129260416654
Content-Length: 297094
Origin: https://websitedojo.com
Connection: keep-alive
Response:
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 16 Oct 2018 10:53:37 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/5.6.37
Access-Control-Allow-Origin: https://websitedojo.com
Access-Control-Allow-Methods: POST, OPTIONS, GET, PUT
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization, X-Requested-With
P3P: CP="NON DSP LAW CUR ADM DEV TAI PSA PSD HIS OUR DEL IND UNI PUR COM NAV INT DEM CNT STA POL HEA PRE LOC IVD SAM IVA OTC"
Access-Control-Max-Age: 1
Vary: User-Agent
Access-Control-Allow-Origin: *
Content-Encoding: gzip
Are there any none-server related things I can try? Or can I run an SSH command to see my serversettings for the necessary settings?
Ok, solved (with new issues but that's fine).
Apache and Nginx were each setting the same header, my host (thanks Mike) has removed the one from apache so only nginx is setting it now.
Update: Two things: One, I was issuing the POST requests for jQuery and Angular from two different domains. I created a jsfiddle to test both requests from the same domain, and they both work. I tried to make the fiddle pretty general so that you can swap out the config values and test an XML POST request with basic http authentication for any site that you need to. The other thing is that, using the Angular $http service, the Data-Type header results in the following error: Request header field Data-Type is not allowed by Access-Control-Allow-Headers in preflight response. So I removed that header. I'm still troubleshooting why the request is working from one domain and not the other. Once I figure that out, I'll update and mark as resolved. /update
The following jQuery POST request with basic authentication works as expected:
var mapstory = {
xml: '<?xml version="1.0" encoding="UTF-8"?> <wfs:Transaction xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" service="WFS" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> <wfs:Update xmlns:feature="http://www.geonode.org/" typeName="geonode:dja_remote_service_edit_test"><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:FeatureId fid="garbage_id" /></ogc:Filter></wfs:Update></wfs:Transaction>',
url: 'https://demo.mapstory.org/geoserver/wfs/WfsDispatcher',
auth: authToken //base64 encoded string of 'user:password'
};
$.ajax({
url: mapstory.url,
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Basic " + mapstory.auth);
},
type: 'POST',
contentType: 'text/html',
dataType: 'xml',
processData: false,
data: mapstory.xml,
success: function(data) {
console.log(data);
}
});
Here are the response headers:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Origin,Content-Type,Accept, Authorization, x-requested-with
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS
Connection: keep-alive
Content-Length: 0
Date: Fri, 01 Jul 2016 21:06:50 GMT
Server: nginx
access-control-allow-origin: http://localhost:8888
However, the following in AngularJS (v1.2.21) doesn't work:
var mapstory = {
xml: '<?xml version="1.0" encoding="UTF-8"?> <wfs:Transaction xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" service="WFS" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> <wfs:Update xmlns:feature="http://www.geonode.org/" typeName="geonode:dja_remote_service_edit_test"><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:FeatureId fid="garbage_id" /></ogc:Filter></wfs:Update></wfs:Transaction>',
url: 'https://demo.mapstory.org/geoserver/wfs/WfsDispatcher',
auth: authToken //base64 encoded string of 'user:password'
};
var config = {
withCredentials: true
};
config.headers = {
'Authorization': 'Basic ' + mapstory.auth,
'Content-Type': 'text/html',
'Data-Type': 'xml'
};
$http.post(mapstory.url, mapstory.xml, config)
.success(function(data) {
console.log(data);
});
I receive the following response headers from this request:
Content-Language: en
Content-Type: text/xml;charset=UTF-8
Date: Fri, 01 Jul 2016 20:52:13 GMT
Server: WSGIServer/0.1 Python/2.7.11
Vary: Accept-Language, Cookie
X-Frame-Options: SAMEORIGIN
I get a valid XML response from the Angular request above, but the response indicates that the request wasn't authorized.
I tried swapping out the Content-Type value with application/xml, but this didn't have any effect on the result.
I've read through the Angular $http documentation and approached a number of other resources, such as this Stack Overflow question which describes a similar issue. A recommended solution is to remove the X-Requested-With default header. This step is apparently not necessary in Angular versions above 1.2 (here's a closed issue for that on Angular's Github), but I tried it anyhow. No luck.
Any guidance on this would be wonderful. Thank you very much for taking the time to read and consider this!
It looks like the server does not recognize angular as a same domain application. So what you must do is to include in the web server headers the value: access-control-allow-origin: * to allow requests from "outside" domains.
First off, I just wanted to say that I have read through all of the other threads relating to this topic, but haven't had any luck. Here's a breakdown of the issue:
Goals
Retrieve a CSRF token from Sails when the Ember Application starts
Inject that CSRF token into every AJAX request that is initiated from the Ember Application
To satisfy goal 1, I created an Ember Initializer that runs when the application first boots up (if there is a better place for this, I'm totally open to suggestions). To satisfy goal 2, I retrieve the CSRF token from Sails and then attempt to use Ember.$.ajaxSetup() to ensure the CSRF token is passed either as a header (X-CSRF-Token) or parameter (_csrf). I also ensure that I'm using the withCredentials option to ensure the cookie is set. Here's the code:
// initializers/csrf.js
import Ember from 'ember';
import config from '../config/environment';
export function initialize() {
Ember.$.get(config.APP.API_URL + '/csrfToken').then(function(result) {
Ember.$.ajaxSetup({
data: {
'_csrf': result._csrf
},
xhrFields: { withCredentials: true }
});
}, function(error) {
console.log(error);
});
}
export default {
name: 'csrf',
initialize: initialize
};
All of this appears to work as I can see in Chrome dev tools that the CSRF token is being retrieved and when I make an AJAX request, I see the data appended to the POST data or added as a header (tried both options). Here's the code I'm running and all of the associated headers:
Ember.$.post(config.APP.API_URL + '/auth/register', {
'email': _this.get('email'),
'password': _this.get('password')
}).then(function(response) {
console.log('It worked!');
});
Request Headers
POST /auth/register HTTP/1.1
Host: localhost:1337
Connection: keep-alive
Content-Length: 82
Accept: */*
Origin: http://localhost:4200
CSP: active
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
DNT: 1
Referer: http://localhost:4200/signup
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: sails.sid=s%3AbrABhErTY3-ytTWOKFJ2KBj7DCAzaLDc.apD60Sd%2BW85GSbTfJ7E3B2PrUwnhOsW6GlNpZTu9jFg
Form Data
_csrf:yP7GDiU2-YGmLBfBvQtMPT3-hRpnfK0x-AfA
email:test#test.com
password:q1w2e3r4
Response Headers
HTTP/1.1 403 Forbidden
Vary: X-HTTP-Method-Override
Access-Control-Allow-Origin: http://localhost:4200
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8
Content-Length: 13
Date: Thu, 09 Jul 2015 08:11:34 GMT
Connection: keep-alive
As you can see from the Response headers, I end up receiving a 403 Forbidden - CSRF Mismatch from Sails. Now, here's where it gets a little weird: first, I'm able to run this just fine with Postman. I retrieve a token and then post that token along with the data to the /auth/register url and it works as expected.
I'm also tried removing the initializer and running the following code:
Ember.$.ajaxSetup({
xhrFields: { withCredentials: true }
});
Ember.$.get(config.APP.API_URL + '/csrfToken').then(function(result) {
Ember.$.post(config.APP.API_URL + '/auth/register', {
'email': _this.get('email'),
'password': _this.get('password'),
'_csrf': result._csrf
}).then(function(response) {
console.log('It worked!');
});
});
This works. However, at this point, I'm at somewhat of a loss as to what the issue actually is. Appreciate any help I can get.
Thanks in advance!
James
#jdixon04, Can you try URL-encoding the CSRF token before sending it through POST? The token mismatch will occur if the token is getting altered from the original.
I found this issue in Github: https://github.com/balderdashy/sails/issues/2266.
I hope this will solve your issue. Do try it and let me know if it works. Thanks.
#jdixon04, got here from your post on my github issue. Actually, isn't the CSRF token going to change at each request made to the server? Then you approach to fix the token when the frontend load cannot cope with this, you may have to fetch the token before each request and use ajaxPrefilter to pass it to the request.
Is that actually related to ember-data-sails? It seems to me you're doing pure ajax here! If you look in my config, you'll realise that pure ajax calls (for authentication as well) are exempted from csrf as I could not make it work as I wished :\ .
Add the x-csrf-token header like this:
Ember.$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': result._csrf
},
xhrFields: { withCredentials: true }
});