I currently have an client hosted on domainA. It reaches out to an endpoint on domainB and I would like to include the cookies from domainA in that request to domainB.
Right now the only cookies that are sent are cookies generated on my machine for domainB.
Is there some sort of security header I can set on the client that allows the sharing of its cookies with domainB or is this a security violation. I can always pass it through as a payload in the body, but it would be nicer if I could just use the withCredentials param to allow it.
// Request
const response = await axios({
method: method as Method,
baseURL,
endpoint,
data,
params,
headers: {
'content-type': 'application/json',
...authorization
},
withCredentials: true // allow sharing of cookies
});
Manually trying to set the cookie header results in the browser complaining Refused to set unsafe header "Cookie"
I think the solution involves the Access-Control-Allow-Headers header on the response headers, but I am unsure
Related
When sending a post request cookie param is getting set in request header.
Is there any way to stop sending cookie param in api request header for a particular api call in angular interceptor
http module by default does not set the cookie params. When you get the response, http module discards the cookie and does not add it in the follow up requests. So you have add it manually:
checkAuth() {
// if we did not add { withCredentials: true }, response would be false becasue, cookies wont be attached
return this.http.get<SignedinResponse>(this.rootUrl + '/signedin',{withCredentials:true}).pipe(
tap(({ authenticated }) => {
// console.log('response from /signedin', res);
})
);
}
you have to add {withCredentials:true} this to each request manually. instead we write interceptor, to modify the req obj and add the cookie by default.
I am running a Flask API which sets cookies (JWT) if username & password is correct.
I am requesting the API from https://example.ngrok.io and the API is located at https://myAPIDomain.com.
The Set-cookie header is present in the response header, but no cookies are set (viewing Chrome application cookie storage).
Here is the backend configuration:
response.headers['Access-Control-Allow-Origin'] = request.headers['Origin']
response.headers.add('Access-Control-Allow-Credentials', 'true')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type')
response.headers.add('Access-Control-Allow-Headers', 'cache-control')
response.headers.add('Access-Control-Allow-Headers', 'X-Requested-With')
response.headers.add('Access-Control-Allow-Headers', 'Authorization')
response.headers.add('Access-Control-Allow-Headers', 'set-cookie')
response.headers.add('Access-Control-Allow-Headers', 'user-agent')
response.headers.add('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE')
Setting cookie in backend:
resp.headers.add("set-cookie",'cookieKey:cookieValue; Domain=myAPIDomain.com; Max-Age=3600; Secure; Path=/; SameSite=None')
Also tried not specifying the domain:
resp.headers.add("set-cookie",'cookieKey:cookieValue; Domain; Max-Age=3600; Secure; Path=/; SameSite=None')
None of these solutions worked.
Here is a picture of the response headers in Chrome:
https://i.imgur.com/D3cq16Z.jpg
The cookies that the API is supposed to set is used for future API endpoint authentication. So when I send another request:
var myHeaders2 = new Headers();
myHeaders2.append("Content-Type", "application/json");
var requestOptions2 = {
method: 'GET',
headers: myHeaders,
redirect: 'follow',
credentials: 'include'
};
fetch("https://myAPIDomain.com/endpointWhichRequiresCookies", requestOptions2)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
But cookies are not sent (obviously since chrome is not setting the cookies). Here is what the backend receives: https://codebeautify.org/online-json-editor/cb81fb64
I know a workaround would be to reply with cookies to frontend as JSON reply and frontend sends the cookies as different headers (since you cannot send "cookie" header from frontend), but this is not the best solution for us.
The only reason we are calling the API from ngrok is because we are doing localhost testing.
The cookies are being set with Postman, so I do not think the backend is at fault here.
Any ideas? We have been at this for days now, without being able to solve the issue.
Found the solution!
We are sending two requests:
Login Post request with username & password (using Fetch POST)
Request to get information from backend (using Fetch GET) - Backend will use the cookies that were set in request #1 to authenticate the request.
Problem was that we didn't send request #1 with credentials: "include", because we didn't think it was needed for the first request. Our second request always had credentials: "include", but apparently Chrome will disregard the cookies if you do not set credentials: "include" on both requests.
Using back end yii2 advanced framework, calling api request using POST method getting the error as: Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response.
const BASE_API_URL = 'http://localhost/harshini/kpa/backend/frontend/web/index.php?r=site%2Flogin';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'})
};
sendValue(message: Kpa) {
return this.http.put(BASE_API_URL, message, httpOptions);
}
Here am adding image please help.
Looks like cors issue,
Enable cors from server side.
Please refer this link Yii2 cors filters error that No 'Access-Control-Allow-Origin' header is present
I am using HTML5 fetch API.
var request = new Request('https://davidwalsh.name/demo/arsenal.json');
fetch(request).then(function(response) {
// Convert to JSON
return response.json();
}).then(function(j) {
// Yay, `j` is a JavaScript object
console.log(JSON.stringify(j));
}).catch(function(error) {
console.log('Request failed', error)
});
I am able to use normal json but unable to fetch the data of above api url.
It throws error:
Fetch API cannot load https://davidwalsh.name/demo/arsenal.json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' 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.
Like epascarello said, the server that hosts the resource needs to have CORS enabled. What you can do on the client side (and probably what you are thinking of) is set the mode of fetch to CORS (although this is the default setting I believe):
fetch(request, {mode: 'cors'});
However this still requires the server to enable CORS as well, and allow your domain to request the resource.
Check out the CORS documentation, and this awesome Udacity video explaining the Same Origin Policy.
You can also use no-cors mode on the client side, but this will just give you an opaque response (you can't read the body, but the response can still be cached by a service worker or consumed by some API's, like <img>):
fetch(request, {mode: 'no-cors'})
.then(function(response) {
console.log(response);
}).catch(function(error) {
console.log('Request failed', error)
});
This worked for me :
npm install -g local-cors-proxy
API endpoint that we want to request that has CORS issues:
https://www.yourdomain.com/test/list
Start Proxy:
lcp --proxyUrl https://www.yourdomain.com
Proxy Active
Proxy Url: http://www.yourdomain.com:28080
Proxy Partial: proxy
PORT: 8010
Then in your client code, new API endpoint:
http://localhost:8010/proxy/test/list
End result will be a request to https://www.yourdomain.ie/test/list without the CORS issues!
Solution to resolve issue in Local env's
I had my front-end code running in http://localhost:3000 and my API(Backend code) running at http://localhost:5000
Was using fetch API to call the API. Initially, it was throwing "cors" error.
Then added this below code in my Backend API code, allowing origin and header from anywhere.
let allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', "*");
res.header('Access-Control-Allow-Headers', "*");
next();
}
app.use(allowCrossDomain);
However you must restrict origins in case of other environments like stage, prod.
Strictly NO for higher environments.
I know this is an older post, but I found what worked for me to fix this error was using the IP address of my server instead of using the domain name within my fetch request.
So for example:
#(original) var request = new Request('https://davidwalsh.name/demo/arsenal.json');
#use IP instead
var request = new Request('https://0.0.0.0/demo/arsenal.json');
fetch(request).then(function(response) {
// Convert to JSON
return response.json();
}).then(function(j) {
// Yay, `j` is a JavaScript object
console.log(JSON.stringify(j));
}).catch(function(error) {
console.log('Request failed', error)
});
You need to set cors header on server side where you are requesting data from.
For example if your backend server is in Ruby on rails, use following code before sending back response. Same headers should be set for any backend server.
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
If you are use nginx try this
#Control-Allow-Origin access
# Authorization headers aren't passed in CORS preflight (OPTIONS) calls. Always return a 200 for options.
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Allow-Origin "https://URL-WHERE-ORIGIN-FROM-HERE " always;
add_header Access-Control-Allow-Methods "GET,OPTIONS" always;
add_header Access-Control-Allow-Headers "x-csrf-token,authorization,content-type,accept,origin,x-requested-with,access-control-allow-origin" always;
if ($request_method = OPTIONS ) {
return 200;
}
Look at https://expressjs.com/en/resources/middleware/cors.html
You have to use cors.
Install:
$ npm install cors
const cors = require('cors');
app.use(cors());
You have to put this code in your node server.
I'm developing an authentication website that authenticate data from a web service. My website is running locally and the web service is running on different domain ex: test.abc.com. if authentication is success then store the response in cookies.
if the data is available in cookies and not expired then in the second call do not ask for authentication but need to validate the user from back end. For that i am using below code.
$.ajax({
url:"https://test.abc.com/test/DummyTest",
method:"GET",
dataType:"json",
beforeSend: function(xhr){
xhr.withCredentials = true;
},
success:function(data){
alert(Success);
},
error:function(xhr,err){
alert("Error");
});
I am using jquery1.6
I have checked the browser Options and the cookies are stored with my localhost ip(160.225.230.50) address. but the web service is in different domain(abc.com). while accessing the second time, I got Error response.
Please help out me on this.
For this to work your auth page should send Access-Control-Allow-Origin and Access-Control-Allow-Credentials headers.
When using Access-Control-Allow-Credentials: true you cannot set Access-Control-Allow-Origin to wildcard, but need to specify origin: Access-Control-Allow-Origin: https://abc.com
Also, there is a simpler way to set xhr fields:
$.ajax({
xhrFields: {
withCredentials: true
},
type: 'POST',
url: ...
});