Custom http Header breaks CORS - javascript

My API has following CORS setup:
(I am the owner, I can change these settings)
Middleware function:
// HeaderMiddleware ...
func HeaderMiddleware(next httprouter.Handle) httprouter.Handle {
return httprouter.Handle(func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-APIKEY")
// ! Production
// if r.Header.Get("X-APIKEY") != "fdfdsf5df6d541cd6" || r.RemoteAddr != frontendURL {
// w.WriteHeader(http.StatusForbidden)
// json.NewEncoder(w).Encode(NoContentResponse{Success: false, Error: "You aren't allowed to request the api here."})
// return
// }
// ! Production
next(w, r, p)
})
}
The X-APIKEY header is not necessary yet, a request without it just works fine:
fetch('http://localhost:8013/tobi#gmx.at/usage', { headers: { } })
.then(response => response.json())
.then(console.log)
returns {used: false} (expected response)
However, if I add the X-APIKEY header:
fetch('http://localhost:8013/tobi#gmx.at/usage', { headers: { 'X-APIKEY': 'sdfsdfsafsf' } })
.then(response => response.json())
.then(console.log)
following error is thrown:
Access to fetch at 'http://localhost:8013/tobiwibu#gmx.at/usage' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.
If I do the request with the X-APIKEY header in Postman, it says that the Access-Control-Allow-Origin header is sent along:
P.S.: I already tried other headers, it works!
If I do the request with chrome (without X-APIKEY header), the Access-Control-Allow-Origin header is sent.
Thanks for your help!

I've now fixed it like this:
I misuse the http Accept header for my API-Token.
Example:
fetch('http://10.0.0.11:8013/lopm#htl/usage',
{"headers":{ "Accept": "fdfdsf5df6d541cd6++" }})
.then(response => response.json())
.then(console.log)
Of course, this isn't a really nice solution, but it does its job.
Thanks for all of you for giving me helpful tips!

Related

How to fix cors error faced even with cors setup on the backend

I have configured my code in this manner on my express backend and have the cors library installed.
I am however getting this error:
Access to fetch at 'mybackend.com' from origin 'domain1.com' 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.
How can I solve this?
My backend and frontend code are as below respectively
const allowedDomains = [
'domain 1',
'domain 2',
];
app.use(cors(
{
origin: function (origin, callback) {
if (allowedDomains.indexOf(origin) != -1) {
callback(null, true);
} else {
callback(new Error(`Access has been blocked `));
}
},
credentials: true,
}
));
await fetch(`mybackend.com' ,{
method:'GET',
headers: new Headers({
'Content-Type':'application/json',
'Authorization':`Bearer ${token}`,
}),
body:null,
})
As per my limited understanding of Fetch API and CORS, I think you have to add mode: 'cors' as well as the header Access-Control-Allow-Origin: '*' or Access-Control-Allow-Origin: 'mybackend.com'. After doing that, your await fetch(...) block would look something like this.
fetch(URL, {
mode: 'cors',
method:'GET',
headers: {
'Access-Control-Allow-Origin':'*',
'Content-Type':'application/json',
'Authorization':`Bearer ${token}`,
},
body:null,
})
.then(response => response.json())
.then(data => { ... });
Hope this helps!

Getting error to make an API Post Call using simple HTML

Without adding mode as 'no-cors':
Error : APICALL.html:1 Access to fetch at 'http://url' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.
I have added mode as 'no-cors' but then i get another error of Bad Request.
Error : APICALL.html:66 POST http://url net::ERR_ABORTED 400 (Bad Request)
Code :
var data = {
Name: "Test",
Category: "Test-Category",
Mobile: "999999999999",
Email: "test#gmail.com",
Question: "Test Question",
};
var options = {
method: "POST",
mode: "no-cors",
origin: "*",
cache: "no-store",
headers: {
"Cache-Control": "no-store",
"Content-Type": "application/json",
},
body: data,
};
fetch("http://url", options)
.then((data) => {
if (!data.ok) {
throw Error(data.status);
}
return data.json();
})
.then((update) => {
console.log(update);
})
.catch((e) => {
console.log(e);
});
Chinese: 因为存在跨域情况,需要后端服务器开启跨域,允许你访问。
English: The server is not enabled to allow this port to cross domains because of cross domain conditions

Cloud function post cors issue

Getting the cors error when sending the request, but working in the postman
Error Message:
Access to fetch at (cloud function url) from origin (my web app) 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.
Cloud Function Code:
exports.add_edit_location_routes = functions.https.onRequest((request, response) => {
let obj = request.body
deletePreviousRoutes(obj.assign_route_id, obj.driver_id, () => addRoutes(obj, (msg) => {
response.send(msg)
}))
})
Request:
fetch("url", {
body: JSON.stringify(json),
method: "POST",
headers: {'Content-Type': 'application/json'},
}).then(res => res.json()).then(obj => console.log(obj))
added this but still not working
res.set('Access-Control-Allow-Origin', '*')
Try including the code you provided in the Cloud Function and not the fetch request.
exports.add_edit_location_routes = functions.https.onRequest((request, response) => {
let obj = request.body
response.set('Access-Control-Allow-Origin', '*')
deletePreviousRoutes(obj.assign_route_id, obj.driver_id, () => addRoutes(obj, (msg) => {
response.send(msg)
}))
})

Angular 6 Http request fails with authorization headers

I'm deploying and angular 6 application that works with a tomcat server in localhost, when I try to execure this http request
this.http
.post<LoginResult>( API_URL + '/login', JSON.stringify(json)/*, { headers: myHeader }*/).pipe(
catchError(this.handleError('get-token', []))).subscribe((response) => {
if(response['result_code'] == 'result_ok') {
this.auth.doSignIn(response['token'], response['name']);
this.router.navigate(['user_manager']);
return true;
}else {
return false;
}
});
everitying works well, but when I add header field
let myHeader = new HttpHeaders().append("Authorization", 'Basic' + this.session.getAccessToken());
this.http
.post<LoginResult>( API_URL + '/login', JSON.stringify(json), { headers: myHeader }).pipe(
catchError(this.handleError('get-token', []))).subscribe((response) => {
if(response['result_code'] == 'result_ok') {
this.auth.doSignIn(response['token'], response['name']);
this.router.navigate(['user_manager']);
return true;
}else {
return false;
}
});
this is my output error:
Access to XMLHttpRequest at 'http://localhost:8095/login' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
HttpErrorResponse
I checked also that the request doesn't arrive to my tomcat server, it is blocked before, that oesn't allow angular to check response headers
Thank you for your help
I'm providing you a generic answer as you have not mention that your server side code is written in which language. You should provide a header from your server code. Provide Access-Control-Allow-Origin header with value as localhost:4200 which will resolve your issue. Or if you want to allow every origin then change its value from localhost:4200 to *.
After reading all the comments I have change something for you.
change your this code let myHeader = new HttpHeaders().append("Authorization", 'Basic' + this.session.getAccessToken()); with const myHeader = new HttpHeaders({'Authorization': 'Bearer ' + localStorage.getItem('api_token')});
and make your post request as
this.http
.post<LoginResult>( API_URL + '/login', json, myHeader).pipe(
catchError(this.handleError('get-token', []))).subscribe((response) => {
if(response['result_code'] == 'result_ok') {
this.auth.doSignIn(response['token'], response['name']);
this.router.navigate(['user_manager']);
return true;
}else {
return false;
}
});
You need to configure CORS on your tomcat server.
You need to tell tomcat which headers the application is allowed to send, so it can include it in the preflight response:
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Authorization,Content-Type,...</param-value>
</init-param>
Take a look at
cors.allowed.methods under CORS Filter section here:
https://tomcat.apache.org/tomcat-7.0-doc/config/filter.html

Angular2 - Cross-Origin Request Blocked

I'm trying to use the forecast API with my angular2 app. However, when i try to access the API I get a Cross-Origin Error. Any idea how i can fix this error ?
search(latitude: any, longitude: any){
console.log(latitude);
console.log(longitude);
let body = 'https://api.forecast.io/forecast/APIKEY/'+latitude+','+longitude ;
console.log(body);
this.http.get(body)
.map(
response => response.json()
).subscribe(
data => console.log("Data: "+data),
err => console.log("Error: "+err),
() => console.log('Get Complete')
);
}
Error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.forecast.io/forecast/APIKEY/37.8267,-122.423. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
Update
Now using JSONP
let body = 'https://api.forecast.io/forecast/APIKEY/'+latitude+','+longitude + '?callback=?' ;
console.log(body);
this.jsonp.get(body)
.map(response => response.json())
.subscribe(
data => console.log("Data: "+data),
err => console.log("Error: "+err),
() => console.log('Get Complete')
);
Error
Error0.def29191127bbc3e0100.hot-update.js:59:10
Object { _body: "JSONP injected script did not invok…", status: 200, ok: true, statusText: "Ok", headers: Object, type: 3, url: "https://api.forecast.io/forecast/60…" }0.def29191127bbc3e0100.hot-update.js:61:10
SyntaxError: expected expression, got '==='
For forecast.io, you should use JSONP. The easiest way to do this using jQuery is adding ?callback=? to request URL:
$.getJSON('https://api.forecast.io/forecast/<API KEY>/' + latitude + ',' + longitude + "?callback=?", function(data) {
console.log(data);
});
I am no expert on Angular 2 but reading the docs it looks like you need to import the Jsonp and then add a callback. More documentation here -- see the section app/wiki/wikipedia.service.ts.
I think something like the code below will work for you
let body = "https://api.forecast.io/forecast/<API KEY>/' + latitude + ',' + longitude + '?callback=?'";
return this.jsonp
.get(body)
.map(response => <string[]> response.json()[1]);
Check out the cors bits on angular.io
https://angular.io/docs/ts/latest/guide/server-communication.html#!#cors
Something like the below (from above)
return this.jsonp
.get(wikiUrl, { search: params })
.map(response => <string[]> response.json()[1]);
You are getting this problem because the header you are sending does not match the headers in the backend.
Suppose you send the following headers:
contentHeaders = new Headers();
contentHeaders.append('Authorization', 'Your token used in app');
contentHeaders.append('Content-Type', 'application/json');
contentHeaders.append('Access-Control-Allow-Origin', '*');
So those headers like Authorization, Content-type, and Access-Control-Allow-Origin should match the allowed headers in your backend.
So in the backend Access-Control-Allow-Headers should have all above headers:
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Authorization, content-type, Access-Control-Allow-Origin");
So here in Access-Control-Allow-Headers you have to pass all headers which you send from frontend: 'Authorization', 'Content-type', and 'Access-Control-Allow-Origin'.
It will work perfectly when you use above concept.
Hope this post will helpful for you
Thanks

Categories

Resources