Browser Cancels PUT requests - xmlhttprequest

I've got a rails api and a react front end with axios to interact with the api. Have enabled CORS in rails, but the below request gets cancelled by the browser and can't find the reason for it.
Request copied as "fetch" call:
fetch("http://localhost:3000/api/v1/profile",
{
"credentials":"include",
"headers":{
"accept":"application/json, text/plain, */*",
"accept-language":"en-GB,en-US;q=0.9,en;q=0.8",
"authorization":"Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwic2NwIjoiYWNjb3VudCIsImF1ZCI6bnVsbCwiaWF0IjoxNTg2OTY4MjIwLCJleHAiOjE1ODcwNTQ2MjAsImp0aSI6IjhkNTE2YjIzLTA1MGQtNGU2MS04ZWE1LWM3ZGIwMzkxNTg0NCJ9.KuwtVNB5minrOs3lvfNjt7lVQSWNRXdqZsbErb6SrGM",
"content-type":"application/json",
"sec-fetch-dest":"empty",
"sec-fetch-mode":"cors",
"sec-fetch-site":"same-site"
},
"referrer":"http://localhost:3001/profile?",
"referrerPolicy":"no-referrer-when-downgrade",
"body":"{\"first_name\":\"testsdasd\",\"last_name\":\"asadeesdfsfs\"}",
"method":"PUT",
"mode":"cors"
});
Is this getting cancelled due to CORS? BTW other post requests are getting through.
Thanks a lot.
Below is the code using axios.
async updateProfileData(profile) {
try {
let axiosResponse = await AxiosClient.instance().put('http://localhost:3000/api/v1/profile', {
first_name: profile.first_name,
last_name: profile.last_name
},{
headers: {
"Content-Type": "application/json"
}
});
return axiosResponse;
} catch (e) {
return e.response;
}
}

Found the answer.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at ‘http://localhost:3000/api/v1/profile’. (Reason: Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’).
https://developer.mozilla.org/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials?utm_source=devtools&utm_medium=firefox-cors-errors&utm_campaign=default

Related

No Set-Cookie header on Axios

I am using a Symfony API backend and want to authenticate by REST call via Axios inside a Vue App.
The authentication works fine when using POSTMAN. It stores a session cookie and resends it on subsequent requests.
However, when I use Axios it won't give me the Set-Cookie header.
What I tried so far:
Adjusted CORS settings on Symfony backend (no CORS errors - all routes working)
Set { withCredentials: true } as config parameter on Axios post request.
Symfony EventSubsriber for injecting CORS headers:
public function onKernelResponse(ResponseEvent $event)
{
$response = $event->getResponse();
$response->headers->set('Access-Control-Allow-Methods', '*');
$response->headers->set('Access-Control-Allow-Headers', [ 'Content-Type', 'Set-Cookie' ]);
$response->headers->set('Access-Control-Allow-Origin', 'http://localhost:3000');
$response->headers->set('Access-Control-Allow-Credentials', 'true');
$response->setStatusCode(200);
}
Note that this is for local testing only.
Axios Request:
login(user, pw) {
return axios.post(cfg.apiUrl + '/api/login', {
username: user,
password: pw
},
{ withCredentials: true }
);
}
Follow up request:
test() {
return axios.get(cfg.apiUrl + '/api/test');
}
Could someone point out what I am still missing? Why do I get the header on POSTMAN, but not on Axios?
The solution is to also add the { withCredentials: true } in further requests. As it seems, it is not possible to read the Set-Cookie header via Axios, as #jub0bs pointed out.
The correct code for a follow-up request looks like:
test() {
return axios.get(cfg.apiUrl + '/api/test', { withCredentials: true });
}

How to set cookie header in post request

Here is my code:
axios
.post(
'https://app.adhg.ashdg/m/api/business/get-business',
{
'gid': getgid,
},
{
headers: {
'Cookie': cookie,
'Content-Type': 'application/x-www-form-urlencoded',
},
},
)
.then(function (response) {
// handle success
alert(JSON.stringify(response.data));
})
.catch(function (error) {
// handle error
alert(error.message);
});
I am implementing Axios post request in my React Native application. I want to send formurlencoded parameters along with the header called cookie.
In cookie I am storing AWS token value to send. But I am not getting the response, it says cookie is not sent. The same URL with params working perfectly in Postman. How can I pass cookie in the header?
Try something like this Cookie: name=value.
Mozilla Web Docs

CORS policy blocking access to Mailchimp API

I am developing a newsletter pop-up using nuxtJS and vuetify.
The process is simple: you enter you email adresse, mailchimp to the rest.
I am having an issue with Mailchimp API.
When I test the API using postman with the same setup, it works fine without any problems. (I can verify by checking the mailchimp account).
But when I try to subscribe through the pop-up, I recieve this error:
Error recieved
This my function code:
let data = {
"email_address": payload,
"status": "subscribed",
"merge_fields": {
"FIRSTNAME": "",
"LASTNAME": ""
}
}
const base64ApiKey = Buffer.from(`c18ab83bd3e9032e080d49f526285039-us6`).toString("base64");
// const base64ApiKey = "c18ab83bd3e9032e080d49f526285039-us6";
this.$axios.post("https://us6.api.mailchimp.com/3.0/lists/c3a3dea1fc/members/", data, {
method: 'POST',
mode: 'no-cors',
headers: {
"Access-Control-Allow-Headers": "Origin, Content-Type, X-Auth-Token, Authorization, Accept,charset,boundary,Content-Length",
"Content-Type": "application/json",
Authorization: `auth ${base64ApiKey}`,
"Access-Control-Allow-Origin": "*",
},
withCredentials: true,
credentials: 'include',
// proxyHeaders: false,
// credentials: false
}).then(res => {
console.log(res.data);
}).catch(err => {
console.log(err);
});
}
It's obviously a CORS problem, I tried on another machine and still have the same error.
A CORS issue is not to be setup on the front-end but rather on the backend/dashboard panel of the service.
So, there is probably a way to whitelist your localhost and production URL on the Mailchip dashboard.
Try to Google this out to find a guide.

React, Axios issue: Response for preflight does not have HTTP ok status ( 404 not found )

I've been trying using axios with basic auth but it always returns not found.
Here is my code
const ROOT_URL='http://localhost/b2b_ecom/b2b-api/index.php/api/';
export function login () {
return function(dispatch)
{
const api = axios.create({
mode: 'no-cors',
credentials:'include',
redirect: 'follow',
auth: {
username: 'mouad#b2b.dz',
password: '123456'
},
headers: {
'Content-Type': 'application/json',
}
});
api.post(`${ROOT_URL}site/login `).then(function(response)
{
dispatch({LOGIN,payload:response.data});
return true;
}).catch(function(error)
{
return error;
});
} ;
}
And here it is the error I got:
OPTIONS http://localhost/b2b_ecom/b2b-api/index.php/api/site/login 404 (Not Found)
Failed to load http://localhost/b2b_ecom/b2b-api/index.php/api/site/login: Response for preflight does not have HTTP ok status.
Screenshot
I think browser is adding access control header to request.
Check the following things
1) When you hit from postman or other such api clients this api should be working properly. (even curl is fine)
2) Try adding Access-Control-Allow-Origin as * for this request on server and see if it works.

Aurelia HttpClient.Fetch to get token from Auth0 but works fine in Postman

I have no trouble getting a bearer token returned when using Postman. However, when using Aurelia, I receive a status 200 with "OK" as the only response. I see that the Request Method is still "OPTIONS". I see this in the Chrome Console:
Failed to load https://------.auth0.com/oauth/token: Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response.
But, from what I can see the headers shown in the response and from what I'm seeing everything looks like it's there.
Here's what I receive from Postman:
Response: Status 200 OK
JSON:
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGci...{shortened for brevity}",
"expires_in": 86400,
"token_type": "Bearer"
}
Here's code from Aurelia:
private getToken() {
var postData = { "client_id": API_CONFIG.clientId, "client_secret": API_CONFIG.clientSecret, "audience": API_CONFIG.audience, "grant_type": "client_credentials" };
this.http.fetch('https://kimberlite.auth0.com/oauth/token', {
credentials: 'omit',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'http://localhost:3000/'
},
mode: 'cors',
method: 'post',
body: JSON.stringify(postData)
}).then(result => result.json())
.then(data => {
localStorage.setItem('api_access_token', data.access_token);
localStorage.setItem('api_expires_at', new Date().getTime() + data.expires_in);
});
}
I've searched and haven't found anything that's helped me get passed this. What am I missing? Any help greatly appreciated
After reading Jesse's comment below, I removed the header for the 'Access-Control-Allow-Origin' and receive the same 200 OK. However, receive error in Google Chrome Origin 'localhost:3000'; 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.".
After reading other questions, I attempted removing all headers and I receive a 401 Unathorized with the following response {{"error":"access_denied","error_description":"Unauthorized"}
private getToken() {
var postData = { "client_id": API_CONFIG.clientId, "client_secret": API_CONFIG.clientSecret, "audience": API_CONFIG.audience, "grant_type": "client_credentials" };
let http = new HttpClient();
http.fetch('https://kimberlite.auth0.com/oauth/token', {
credentials: 'omit',
//headers: {
// 'Content-Type': 'application/json'
//},
mode: 'cors',
method: 'post',
body: JSON.stringify(postData)
}).then(result => result.json())
.then(data => {
localStorage.setItem('api_access_token', data.access_token);
localStorage.setItem('api_expires_at', new Date().getTime() + data.expires_in);
});
}
ok, I just tried in Firefox, using only the 'Content-Type' header and received expected response. Is there something with Chrome (which most users are going to be using) that I need to be aware of?
You shouldn't set the access-control-allow-origin header on the request. In a CORS request, the server endpoint needs to set this header on the response of your OPTIONS request.
The way that Cross-Origin Resource Sharing works, is that the client first makes an OPTIONS call to the server endpoint. The server endpoint should be configured to use CORS, and have a list of origins that are allowed (or simply a * to allow all origins). Then on the response to this OPTIONS request, the server will set the Access-Control-Allow-Origin: https://localhost:3000 to indicate the origin is allowed to make the request. You can see this in your response too:
The client then proceeds to make the GET or POST call to the same endpoint and actually retrieve/store the data.
In your case, if you make the request using the Aurelia fetch client, you don't need to set a header to do this. You can simply do the following:
private getToken() {
var postData = { "client_id": API_CONFIG.clientId, "client_secret": API_CONFIG.clientSecret, "audience": API_CONFIG.audience, "grant_type": "client_credentials" };
this.http.fetch('https://kimberlite.auth0.com/oauth/token', {
credentials: 'omit',
headers: {
'Content-Type': 'application/json'
},
mode: 'cors',
method: 'post',
body: JSON.stringify(postData)
}).then(result => result.json())
.then(data => {
localStorage.setItem('api_access_token', data.access_token);
localStorage.setItem('api_expires_at', new Date().getTime() + data.expires_in);
});
}