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

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);
});
}

Related

VueJs axios unauthorized POST request with Authorization header

I want to send POST with authorization to my REST api, but keep getting unauthorized. Everything works in postman, I have CORS enabled on the server.
axios
.post("/api/listings", {
headers: {
'Authorization': 'Bearer ' + this.token,
}
The header seems to appear to request payload in chrome debuggin tools.
I get the token from localStorage and it is definitely there.
My issue was that the header was being sent as an object in request body and not as a header.
Fixed the issue using this code:
axios
.request({
url: "api/listings",
method: "POST",
headers: {
Authorization: "Bearer " + this.token,
},
data:{
ListingName: this.name
}
})
.then((response) => {
console.log(response);
});
}

Express Node.js Cors preflight issue 400 net::ERR_FAILED

I have been banging my head against the wall for hours now... tried every type of combination to get this working.
I have my own API endpoint here: https://app.automate.mn/api/tools/email/add
Which I am trying to post data to from 3rd party websites.
app.js
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.options('*', cors());
...
const {addContact} = require('./routes/api/tools/email');
app.post('/api/tools/email/add', addContact);
addContact.js
addContact: async function (req, res) {
res.status(200).send('OK - TEST');
return;
}
I have setup a test website here with the form: https://demoautomatemn.wpcomstaging.com/
When you submit the form, it's posting the data to the endpoint:
loadForm.js
automate_post_data('https://app.automate.mn/api/tools/email/add', data)
.then(data => {
console.log(data); // JSON data parsed by `data.json()` call
});
async function automate_post_data(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST',
mode: 'cors', // no-cors, *cors, same-origin
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
//referrerPolicy: 'origin', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status} - ${response.statusText}`);
}
return response.json();
}
The post is failing:
Access to fetch at 'https://app.automate.mn/api/tools/email/add' from origin 'https://demoautomatemn.wpcomstaging.com' 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.
loadForm.js:109 POST https://app.automate.mn/api/tools/email/add net::ERR_FAILED
I was expecting to see the "Access-Control-Allow-Origin" in the response headers for the OPTION call but nothing (Preflight response is not successful). I have tried everything to get it working.
Any suggestions would be so welcome right now.
OK, Progress but no cigar!
I setup the following:
Setting at apache level:
https://docs.bitnami.com/bch/infrastructure/nodejs/administration/enable-cors-nodejs/
You might also find this helpful: https://enable-cors.org/server_apache.html
Adding origin to the request
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Origin': window.location.href
},
referrerPolicy: 'origin',
This then resulted in the error message changing:
Access to fetch at 'https://app.automate.mn/api/tools/email/add' from origin 'https://demoautomatemn.wpcomstaging.com' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
Update 'Content-Type': 'application/x-www-form-urlencoded',
As per this post: Why doesn't adding CORS headers to an OPTIONS route allow browsers to access my API?
I updated the request to x-www-form-urlencoded
const response = await fetch(url, {
method: method,
mode: 'cors', // no-cors, *cors, same-origin
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Origin': window.location.href
},
referrerPolicy: 'origin', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: data // body data type must match "Content-Type" header
});
It feels like progress however I am still getting 406 error:
POST https://app.automate.mn/api/tools/email/add 406
Response {type: "cors", url: "https://app.automate.mn/api/tools/email/add", redirected: false, status: 406, ok: false, …}

how to use axios to send data to line notify

I tried to send data to line notify server by axios and it fail
I have tried 2 version of code. as shown below
version 1 :
axios({
method: "post",
url: "https://notify-api.line.me/api/notify",
data: 'message="from vue"',
config: {
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "multipart/form-data"
}
},
Authorization: "Bearer [my token]"
})
.then(function(response) {
console.log(response);
})
.catch(function(response) {
console.log(response);
});
response is
XMLHttpRequest cannot load https://notify-api.line.me/api/notify due to access control checks.
Error: Network Error
and version 2 is :
axios
.post("https://notify-api.line.me/api/notify", "message=from vue", {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "Bearer [my token]"
}
})
.then(response => {
console.log(response);
});
response is
Preflight response is not successful
XMLHttpRequest cannot load https://notify-api.line.me/api/notify due to access control checks.
Error: Network Error
What wrong with is
but I have tried in postman it work fine
Oh I am too familiar with this. Heres an explanation on stackoverflow as to why your request works with postman but not in browser. Long story short browsers send a preflight options check that will ask the server if the action you're about to perform is allowed. Postman does not. Usually the "Access-Control-Allow-Origin": "*" header is sent by the server to the browser not the other way around.
Inside the docs for LINE Notify you can find:
POST https://notify-api.line.me/api/notify
Sends notifications to users or groups that are related to an access token.
If this API receives a status code 401 when called, the access token will be deactivated on LINE Notify (disabled by the user in most cases). Connected services will also delete the connection information.
Requests use POST method with application/x-www-form-urlencoded (Identical to the default HTML form transfer type).
My guess is that your access_token might have been deactivated. Try requiring a new access token and doing the request again.
I think it is impossible to connect directly to the external url for the axios cuz ajax is basically for the inner data network. But you might have a controller if you do a web project, so you can just use your controller language to make a connection with line notify. In my case, I made a rails project and used axios in the vue.js, so I made a link like this.
View(axios) => Controller(Ruby) => LineAPI
me currently work on this too.
I did my app with node js.
My way below is for your reference, it works well.
const axios = require('axios');
const querystring = require('querystring');
axios({
method: 'post',
url: 'https://notify-api.line.me/api/notify',
headers: {
'Authorization': 'Bearer ' + 'YOUR_ACCESS_TOKEN',
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*'
},
data: querystring.stringify({
message: 'something you would like to push',
})
})
.then( function(res) {
console.log(res.data);
})
.catch( function(err) {
console.error(err);
});
I try it works.
async function test() {
const result = await axios({
method: "post",
url: "https://notify-api.line.me/api/notify",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Bearer [token]",
},
data: 'message=你好哇'
})
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
});
}
test();
I think you can check response on chrome debugger network.
or provide more information, thx.

How do I resolve the CORS error in Yelp API call?

I'm trying to call the Yelp Fusion API using AJAX but I'm getting the following error below. Could someone help me figure out what's going on here?
api.yelp.com/v3/:1 Failed to load resource: the server responded with a status of 403 ()
index.html:1 Access to XMLHttpRequest at 'https://api.yelp.com/v3/' 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.
Here's the code I'm using:
var queryURL = "https://api.yelp.com/v3/";
var apiKey = "my key"
$.ajax({
url: queryURL,
method: "GET",
headers: {
"accept": "application/json",
"Access-Control-Allow-Origin":"*",
"Authorization": `Bearer ${apiKey}`
}
}).then(function(res) {
var results = res.data
console.log(results);
});
Try using the CORSAnywhere proxy, plug your key in the snip below and give it a shot:
// JavaScript Document
var queryURL = "https://cors-anywhere.herokuapp.com/https://api.yelp.com/v3/";
var apiKey = "my key";
$.ajax({
url: queryURL,
method: "GET",
headers: {
"accept": "application/json",
"x-requested-with": "xmlhttprequest",
"Access-Control-Allow-Origin":"*",
"Authorization": `Bearer ${apiKey}`
},
success: function(result){
console.log(result);
}
});

AXIOS POST failed access control check: No 'Access-Control-Allow-Origin' .HTTP status code 405

I don't know what I did wrong and need help.
function loadDoy() {
axios({
method: 'post',
headers: {
"Access-Control-Allow-Origin": "*",
'Content-Type': 'application/json',
},
url: apiPostUrl,
data: {
user: "webuser",
password: "m0nk3yb#rz",
layout: "Main Menu"
},
})
.then(function(response) {
this.token = response.data.token;
//if login token works then get records
getRecords();
})
.catch(function(xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
});
}
You can use 'crossDomain': true at your header of axios post, this is due to cors error. Your browser is making a Preflight Request, which uses the OPTIONS HTTP method. This is to check whether the server will allow the POST request – the 405 status code is sent in the response to the OPTIONS request, not your POST request
In this case, the following is causing the request to be preflighted:
if the Content-Type header has a value other than the following:
application/x-www-form-urlencoded
multipart/form-data
text/plain
The value for the Content-Type header is set to application/json;charset=utf-8 by axios. Using text/plain;charset=utf-8 or text/plain fixes the problem: You may try using like below.
source: App Script sends 405 response when trying to send a POST request
axios({
method: 'post',
headers: {
'crossDomain': true,
//'Content-Type': 'application/json',
'Content-Type': 'text/plain;charset=utf-8',
},
url: apiPostUrl,
data: {
user: "webuser",
password: "m0nk3yb#rz",
layout: "Main Menu"
},
})
.then(function(response) {
this.token = response.data.token;
//if login token works then get records
getRecords();
})
.catch(function(xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
});