how to fix '403 (Forbidden)' on a $http.get request to etherpad - angularjs

[header][1]
[header][2]
i am trying to send a get request to etherpad hosted in a different domain. the OPTIONS preflight request goes through but the get request returns 403 status.
however when i install CORS for chrome extension the request goes through
when i install cors chrome extension the request goes through
here is my code:
/* ........ export draft to html/pdf/word ........ */
//get content for this template
var url = Drafting.domain + Drafting.port + '/p/' + Drafting.padID + '/export/html?' + 'apikey=' + Drafting.apikey;
$http.get(url).then(function(response, status){
if(typeof(callback)==='function' && callback)
{
callback(response.data);
}
});
```}
[1]: https://i.stack.imgur.com/25dsj.png
[2]: https://i.stack.imgur.com/ivHnn.png

i just passed 'withCredentials:true' together with the url and then modified the importexport.js inside the etherpad files where 'AccessControlAllowOrigin' was set to '*' i replaced it with a specific domain and it worked.

Related

CORS error with react native app run with expo web [duplicate]

I created an API endpoint using Google Cloud Functions and am trying to call it from a JS fetch function.
I am running into errors that I am pretty sure are related to either CORS or the output format, but I'm not really sure what is going on. A few other SO questions are similar, and helped me realize I needed to remove the mode: "no-cors". Most mention enabling CORS on the BE, so I added response.headers.set('Access-Control-Allow-Origin', '*') - which I learned of in this article - to ensure CORS would be enabled... But I still get the "Failed to fetch" error.
The Full Errors (reproducible in the live demo linked below) are:
Uncaught Error: Cannot add node 1 because a node with that id is
already in the Store. (This one is probably unrelated?)
Access to fetch at
'https://us-central1-stargazr-ncc-2893.cloudfunctions.net/nearest_csc?lat=37.75&lon=-122.5'
from origin 'https://o2gxx.csb.app' has been blocked by CORS policy:
Request header field access-control-allow-origin is not allowed by
Access-Control-Allow-Headers in preflight response.
GET
https://us-central1-stargazr-ncc-2893.cloudfunctions.net/nearest_csc?lat=37.75&lon=-122.5 net::ERR_FAILED
Uncaught (in promise) TypeError: Failed to fetch
See Code Snippets below, please note where I used <---- *** Message *** to denote parts of the code that have recently changed, giving me one of those two errors.
Front End Code:
function getCSC() {
let lat = 37.75;
let lng = -122.5;
fetch(
`https://us-central1-stargazr-ncc-2893.cloudfunctions.net/nearest_csc?lat=${lat}&lon=${lng}`,
{
method: "GET",
// mode: "no-cors", <---- **Uncommenting this predictably gets rid of CORS error but returns a Opaque object which seems to have no data**
headers: {
// Accept: "application/json", <---- **Originally BE returned stringified json. Not sure if I should be returning it as something else or if this is still needed**
Origin: "https://lget3.csb.app",
"Access-Control-Allow-Origin": "*"
}
}
)
.then(response => {
console.log(response);
console.log(response.json());
});
}
Back End Code:
import json
import math
import os
import flask
def nearest_csc(request):
"""
args: request object w/ args for lat/lon
returns: String, either with json representation of nearest site information or an error message
"""
lat = request.args.get('lat', type = float)
lon = request.args.get('lon', type = float)
# Get list of all csc site locations
with open(file_path, 'r') as f:
data = json.load(f)
nearby_csc = []
# Removed from snippet for clarity:
# populate nearby_csc (list) with sites (dictionaries) as elems
# Determine which site is the closest, assigned to var 'closest_site'
# Grab site url and return site data if within 100 km
if dist_km < 100:
closest_site['dist_km'] = dist_km
// return json.dumps(closest_site) <--- **Original return statement. Added 4 lines below in an attempt to get CORS set up, but did not seem to work**
response = flask.jsonify(closest_site)
response.headers.set('Access-Control-Allow-Origin', '*')
response.headers.set('Access-Control-Allow-Methods', 'GET, POST')
return response
return "No sites found within 100 km"
Fuller context for code snippets above:
Here is a Code Sandbox Demo of the above.
Here is the full BE code on GitHub, minus the most recent attempt at adding CORS.
The API endpoint.
I'm also wondering if it's possible that CodeSandbox does CORS in a weird way, but have had the same issue running it on localhost:3000, and of course in prod would have this on my own personal domain.
The Error would appear to be CORS-related ( 'https://o2gxx.csb.app' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.) but I thought adding response.headers.set('Access-Control-Allow-Origin', '*') would solve that. Do I need to change something else on the BE? On the FE?
TLDR;
I am getting the Errors "Failed to fetch" and "field access-control-allow-origin is not allowed by Access-Control-Allow-Headers" even after attempts to enable CORS on backend and add headers to FE. See the links above for live demo of code.
Drop the part of your frontend code that adds a Access-Control-Allow-Origin header.
Never add Access-Control-Allow-Origin as a request header in your frontend code.
The only effect that’ll ever have is a negative one: it’ll cause browsers to do CORS preflight OPTIONS requests even in cases when the actual (GET, POST, etc.) request from your frontend code would otherwise not trigger a preflight. And then the preflight will fail with this message:
Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response
…that is, it’ll fail with that unless the server the request is being made to has been configured to send an Access-Control-Allow-Headers: Access-Control-Allow-Origin response header.
But you never want Access-Control-Allow-Origin in the Access-Control-Allow-Headers response-header value. If that ends up making things work, you’re actually just fixing the wrong problem. Because the real fix is: never set Access-Control-Allow-Origin as a request header.
Intuitively, it may seem logical to look at it as “I’ve set Access-Control-Allow-Origin both in the request and in the response, so that should be better than just having it in the response” — but it’s actually worse than only setting it in the response (for the reasons described above).
So the bottom line: Access-Control-Allow-Origin is solely a response header, not a request header. You only ever want to set it in server-side response code, not frontend JavaScript code.
The code in the question was also trying to add an Origin header. You also never want to try to set that header in your frontend JavaScript code.
Unlike the case with the Access-Control-Allow-Origin header, Origin is actually a request header — but it’s a special header that’s controlled completely by browsers, and browsers won’t ever allow your frontend JavaScript code to set it. So don’t ever try to.

My code fails for https with bad request and works for http

I have tried everything available on line but in vain. The code below works for http and not https.
I have tls 1.2 enable on my system and ssl certificate is self signed that I am using with https and using IIS web server from MS.
Also when I try to access the url from IIS Browse Website I see the same error with these details:
This error (HTTP 400 Bad Request) means that Internet Explorer was able to connect to the web server, but the webpage could not be found because of a problem with the address.
But there are no issues with the address.
I also see this error in the event viewer:
The application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID
{2593F8B9-4EAF-457C-B68A-50F6B8EA6B54}
and APPID
{15C20B67-12E7-4BB6-92BB-7AFF07997402}
to the user CORP\qahee SID (S-1-5-21-606747145-1993962763-839522115-104115) from address LocalHost (Using LRPC) running in the application container Unavailable SID (Unavailable). This security permission can be modified using the Component Services administrative tool.
Though I have changed the permission to full control in the registry for the user CORP\qahee and have rebooted the system before trying again I still get the error.
I have all three version of tls enabled in the registry and also in the internet options.
I wonder if the issue is due to self signed certificate.
Here is my code:
private string GetSessionId(string id)
{
var url
System.Configuration.ConfigurationManager.AppSettings["SessionServerURL"] ??"http://localhost";
System.Net.ServicePointManager.SecurityProtocol |=
System.Net.SecurityProtocolType.Tls12 |
System.Net.SecurityProtocolType.Tls11 |
System.Net.SecurityProtocolType.Tls;
using (var handler = new HttpClientHandler() { UseDefaultCredentials =
true })
{
handler.ServerCertificateCustomValidationCallback =
ServerCertificateCustomValidation;
using (var client = new HttpClient(handler))
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
newMediaTypeWithQualityHeaderValue("application/json"));
logger.Debug("handler: " + handler + " url: " + url +
" BaseAddress: " + client.BaseAddress);
// HTTP GET
try
{
HttpResponseMessage response =
client.GetAsync("/System/StartSession/" + id).Result;
logger.Debug("response status: " +
response.StatusCode +
" req msg: " + response.RequestMessage +
" reasonphrase:+response.ReasonPhrase);
if (response.IsSuccessStatusCode)
{
var jsonText =
response.Content.ReadAsStringAsync().Result;
var result =
JsonConvert.DeserializeObject<string>(jsonText);
return result;
}
}
This is the output for http when it runs w/o failure:
response status: OK req msg: Method: GET, RequestUri: 'http://localhost:83/System/StartSession/434f52505c7161686565', Version: 1.1, Content: , Headers:
{
Accept: application/json
} reason phrase: OK
For https this is the failure I get
response status: BadRequest req msg: Method: GET, RequestUri: 'https://abe-s19-qe1.qae.xxx.com:444/System/StartSession/434f52505c7161686565', Version: 1.1, Content: , Headers:
{
Accept: application/json
} reason phrase: Bad Request

In React, how do I get the value of a response header in an interceptor?

I'm using React 16 and the fetch-interceptor library. I have this in a file called src/interceptors/fetch.js ...
import fetchIntercept from 'fetch-intercept';
const unregister = fetchIntercept.register({
response: function (response) {
console.log("\n\ncalled function!");
console.log("body:" + response.body);
// Do something with the response
console.log(response.headers);
console.log("header: " + response.headers.get('Refresh-Token') );
if (response.ok && 'Refresh-Token' in response) {
const token = response['Refresh-Token'];
console.log("saving " + token);
sessionStorage.setItem('token', token)
}
return response;
},
});
In my src/App.js component, I include it like so
import { unregister } from "./interceptors/fetch.js";
but when I make a fetch call, I can't seem to get any headers. The console line
console.log("header: " + response.headers.get('Refresh-Token') );
prints out
header: null
despite the fact in my Chrome Devtools, I see
. Access-Control-Allow-Origin: http://localhost:3000
. Allow: POST, OPTIONS
. Content-Length: 196
. Content-Type: application/json
. Date: Tue, 05 Jul 2022 14:48:49 GMT
. Referrer-Policy: same-origin
. Refresh-Token: f7c622e042b38a9fc2c594a914c2fe38ffa8fb53
. Server: WSGIServer/0.2 CPython/3.9.1
. Vary: Accept, Origin
. X-Content-Type-Options: nosniff
. 
X-Frame-Options: DENY
under the "Response Headers" section. I get the same result in consolelog if I try and query other types of headers, e.g. "Content-Type". What's the right way to get my header value?
Edit: In response to the answer given, the output of the console log is
. {content-length: '180', content-type: 'application/json'}
. content-length: "180"

. content-type: "application/json"
which is odd that only those two headers are showing up, because from Chrome devtools, there are many more headers (notice the content-length matches)
If you go through the specs of fetch API on MDN, you will see that it has a fixed set of headers that are readable by the scripts for CORS requests, and to allow more headers you will need to add them to the allow list using Access-Control-Expose-Headers(assuming you have access to the server).
The Access-Control-Expose-Headers response header allows a server to indicate which response headers should be made available to scripts running in the browser, in response to a cross-origin request.
It's not like these headers can't be accessed at all, but the browser will respect the specs and not allow reading non-allowed headers by scripts running on the page. That's why you can see the headers in the network tab but your script is not able to access the custom headers.
The Response object's headers does have a headers.get() method, so you are correctly calling that.
Your 'Refresh-Token' in response and response['Refresh-Token'] expressions don't look correct, but as you say, you are seeing your null value before that.
It is difficult to say why that is returning null without seeing the exact response, but one way you can debug this is by getting the entries() of your headers, and convert them to a plain object via Object.fromEntries(). This might be easier to inspect in your console.
See this example -
const unregister = fetchIntercept.register({
response: function (response) {
console.log("response:", response);
const headersObj = Object.fromEntries([...response.headers.entries()]);
console.log(headersObj);
return response;
}
});
Otherwise, for the other parts of your code, to check if a header exists: useresponse.headers.has(key) instead of key in response.headers, and to get the header, use response.headers.get(key) instead of response[key].

reactJS app with a fetch to an API fails to load with No 'Access-Control-Allow-Origin' header is present on the requested resource

I have the following code which worked 6 days ago:
function showProduct(barcode) {
let url = "https://api.barcodelookup.com/v2/products?barcode=" + barcode + "&key=mj1pm32ylcctxj1byaiaxxxxxxxxxx";
const options = { method: 'GET' };
fetch(url, options)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
setTimeout(function(){
if (myJson == undefined)
{
console.log("fetch failed")
}
else
{
//inspect the data that the WebAPI returned
console.log("myJson: ", myJson);
console.log(myJson.products[0].barcode_formats);
Quagga.stop();
}
}, 3000);
});
}
and the value being passed into the function is 5000159459228. When I executed this code last week, I was receiving a response back from the API and I was able to pick up the individual fields being returned.
Today, I started debugging a different feature of my app and now I receive this error when executing the above listed code:
Failed to load https://api.barcodelookup.com/v2/products?barcode=5000159459228&key=mj1pm32ylcctxj1byaiaxxxxxxxxxx: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
followed by this error:
Uncaught (in promise) TypeError: Failed to fetch
and then this:
newscan:91 Cross-Origin Read Blocking (CORB) blocked cross-origin response https://api.barcodelookup.com/v2/products?barcode=5000159459228&key=mj1pm32ylcctxj1byaiaxxxxxxxxxx with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
If I manually paste the string that I build into the url variable into a browser, I do get a valid response back.
Any suggestions?
Jonathan what you have there is a cors problem. A quick way to solve that if you are using express in your backend is just add CORS module with npm i --save cors and then use it as a middleware:
const cors = require('cors');
app.use(cors());
You can always add the headers yourself. Take a deepr look at Enable CORS.org
Your question was also answered here: [No 'Access-Control-Allow-Origin' header is present on the requested resource—when trying to get data from a REST API

NetworkError: 405 Method Not Allowed AngularJS REST

In AngularJS, I had the following function, which worked fine:
$http.get( "fruits.json" ).success( $scope.handleLoaded );
Now I would like to change this from a file to a url (that returns json using some sweet Laravel 4):
$http.get( "http://localhost/fruitapp/fruits").success( $scope.handleLoaded );
The error I get is:
"NetworkError: 405 Method Not Allowed - http://localhost/fruitapp/fruits"
What's the problem? Is it because fruit.json was "local" and localhost is not?
From w3:
10.4.6 405 Method Not Allowed
The method specified in the Request-Line is not allowed for the resource
identified by the Request-URI. The response MUST include an Allow header
containing a list of valid methods for the requested resource.
It means the for the URL: http://localhost/fruitapp/fruits The server is responding that the GET method isn't allowed. Is it a POST or PUT?
The angular js version you are using would be <= 1.2.9.
If Yes, try this.
return $http({
url: 'http://localhost/fruitapp/fruits',
method: "GET",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
I had a similar issue with my SpringBoot project, I was getting the same error in the browser console but I saw a different error message when I looked at the back-end log, It was throwing this error: "org.springframework.web.HttpRequestMethodNotSupportedException, message=Request method 'DELETE' not supported " It turned out that I was missing the {id} parameter in the back-end controller:
** Wrong code :**
#RequestMapping(value="books",method=RequestMethod.DELETE)
public Book delete(#PathVariable long id){
Book deletedBook = bookRepository.findOne(id);
bookRepository.delete(id);
return deletedBook;
}
** Correct code :**
#RequestMapping(value="books/{id}",method=RequestMethod.DELETE)
public Book delete(#PathVariable long id){
Book deletedBook = bookRepository.findOne(id);
bookRepository.delete(id);
return deletedBook;
}
For me, it was the server not being configured for CORS.
Here is how I did it on Azure: CORS enabling on Azure
I hope something similar works with your server, too.
I also found a proposal how to configure CORS on the web.config, but no guarantee: configure CORS in the web.config. In general, there is a preflight request to your server, and if you did a cross-origin request (that is from another url than your server has), you need to allow all origins on your server (Access-Control-Allow-Origin *).

Resources