{"error":"invalid_client"} client credentials error spotify with express - javascript

I am developping an api on spotify.
I want to retrieve clients credentials. I set up my app on the dashboard.
My client_id and secret are correct.
But I have the same error at the end when I try to retrieve this client credential: "error":"invalid_client"
I look for my problem on web but no one correspond to my problem.
Here is my code:
`
const express = require("express");
const path = require("path");
const cors = require("cors");
const fetch = (...args) =>
import('node-fetch').then(({default: fetch}) => fetch(...args));
const request = "https://accounts.spotify.com/api/token";
const code = Buffer.from(client_id + ":" + client_secret).toString("base64");
const app = express();
const optionsTOKEN = {
method: "POST",
body: "grant_type=client_credentials",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic" +code
},
// json: true,
};
app.get("/code", async (req, res) => {
const data = await retrieveCode(request, optionsTOKEN);
console.log(res.statusCode)
res.send(data);
});
app.listen(8888, () => {
console.log("server running on port 8888");
});
async function retrieveCode(URlRequest, options) {
try {
const res = await fetch(URlRequest, options);
console.log(res);
const data = await res.json();
console.log("la data vaut" + data);
return data
} catch (err) {
console.log(`L'erreur: ${err}`);
}
}
`
Thank you for your help
I try to modify the parameters in my options, set up a new project on my dahsboard, change my port.
I am expecting to retrieve the access token

You needs to add a space between "Basic" and code
before
"Basic" +code
After
"Basic " +code
#1 With this code
This full test code with hide client_id and client_secret
const express = require("express");
const fetch = (...args) =>
import('node-fetch').then(({ default: fetch }) => fetch(...args));
const request = "https://accounts.spotify.com/api/token";
const client_id = "32-your-client-id-7b";
const client_secret = "ab-your-client_secret-9e";
const code = Buffer.from(client_id + ":" + client_secret).toString("base64");
const app = express();
const optionsTOKEN = {
method: "POST",
body: "grant_type=client_credentials",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic " + code
},
// json: true,
};
app.get("/code", async (req, res) => {
const data = await retrieveCode(request, optionsTOKEN);
console.log(res.statusCode)
res.send(data);
});
app.listen(8888, () => {
console.log("server running on port 8888");
});
async function retrieveCode(URlRequest, options) {
try {
const res = await fetch(URlRequest, options);
console.log(res);
const data = await res.json();
console.log("la data vaut" + JSON.stringify(data));
return data
} catch (err) {
console.log(`L'erreur: ${err}`);
}
}
#2 Using this dependencies
package.json for npm install
{
"dependencies": {
"express": "^4.18.2",
"node-fetch": "^3.3.0"
}
}
#3 npm install
#4 npm start
#5 access from browser http://localhost:8888/code
Response in console
la data vaut{"access_token":"BQCuVhXlpVQGKGxqK-remove-some-string-nX6sQp8uPSYBMh5lsU","token_type":"Bearer","expires_in":3600}
200
In Browser,

Related

Etsy API authetication - Cannot GET error

I'm very rusty in javascript and haven't touched it in a decade so I was following an Etsy tutorial on how to request an API access token.
I'm running a node.js node on my localhost and ngrok to get a proper URL for it (seems like localhost doesn't work for etsy). The authentication seems to work (I can log in in etsy with it), until the part in the tutorial where I need to send the API information onto the next page (to actually start pulling the etsy store data).
As soon as the etsy authentication page get redirected to the next page I alway get the error "Cannot GET views/index.hbs"
The page is in the views folder in the project folder.
I'm really not sure what the problem is, maybe the way the files are structured in the folder?
Thanks a lot for the help.
This is how the code looks like:
// Import the express library
const express = require('express')
const fetch = require("node-fetch");
const hbs = require("hbs");
// Create a new express application
const app = express();
app.set("view engine", "hbs");
app.set("views", `${process.cwd()}/views`);
// Send a JSON response to a default get request
app.get('/ping', async (req, res) => {
const requestOptions = {
'method': 'GET',
'headers': {
'x-api-key': 'xxxxxxxxxxxxxxx',
},
};
const response = await fetch(
'https://api.etsy.com/v3/application/openapi-ping',
requestOptions
);
if (response.ok) {
const data = await response.json();
res.send(data);
} else {
res.send("oops");
}
});
// This renders our `index.hbs` file.
app.get('/', async (req, res) => {
res.render("index");
});
/**
These variables contain your API Key, the state sent
in the initial authorization request, and the client verifier compliment
to the code_challenge sent with the initial authorization request
*/
const clientID = 'xxxxxxxxxxxxxxxx';
const clientVerifier = 'xxxxxxxxxxxxxxxxxxxxxx';
const redirectUri = 'https://xxxxxxx/views/index.hbs';
app.get("/oauth/redirect", async (req, res) => {
// The req.query object has the query params that Etsy authentication sends
// to this route. The authorization code is in the `code` param
const authCode = req.query.code;
const tokenUrl = 'https://api.etsy.com/v3/public/oauth/token';
const requestOptions = {
method: 'POST',
body: JSON.stringify({
grant_type: 'authorization_code',
client_id: clientID,
redirect_uri: redirectUri,
code: authCode,
code_verifier: clientVerifier,
}),
headers: {
'Content-Type': 'application/json'
}
};
const response = await fetch(tokenUrl, requestOptions);
// Extract the access token from the response access_token data field
if (response.ok) {
const tokenData = await response.json();
res.send(tokenData);
} else {
res.send("oops");
}
});
app.get("/welcome", async (req, res) => {
// We passed the access token in via the querystring
const { access_token } = req.query;
// An Etsy access token includes your shop/user ID
// as a token prefix, so we can extract that too
const user_id = access_token.split('.')[0];
const requestOptions = {
headers: {
'x-api-key': clientID,
// Scoped endpoints require a bearer token
Authorization: `Bearer ${access_token}`,
}
};
const response = await fetch(
`https://api.etsy.com/v3/application/users/${user_id}`,
requestOptions
);
if (response.ok) {
const userData = await response.json();
// Load the template with the first name as a template variable.
res.render("welcome", {
first_name: userData.first_name
});
} else {
res.send("oops");
}
});
// Start the server on port 3003
const port = 3003;
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});

App deployed on Heroku but api calls are now failing (Failed to load resource: net::ERR_CONNECTION_REFUSED, TypeError: Failed to fetch)

My app is successfully deployed on Heroku- it works when I have VSCode open and do npm run start manually, however when I close VSCode it is no longer able to successfully call any APIs on the backend and the console shows me a bunch of errors like the one in the title.
my console (ONLY happens when I close VSCode):
my code in the backend:
const PORT = 8000
const express = require('express')
const cors = require('cors')
const {TwitterApi} = require('twitter-api-v2')
const axios = require('axios')
const cheerio = require('cheerio')
require('dotenv').config()
const snoowrap = require('snoowrap')
const linkPreviewGenerator = require('link-preview-generator')
const spotify = require('spotify-web-api-node')
const fetch = require('node-fetch')
var request = require('request')
const app = express()
app.use(cors())
app.get('/', async (req, res) => {
const client = new TwitterApi(process.env.twt_bearer_token)
const trendsInternational = await client.v1.trendsByPlace(1);
const trendList = []
for (const {trends} of trendsInternational) {
for (const trend of trends) {
trendList.push({
name: trend.name,
url: trend.url
})
}
}
res.json(trendList)
})
app.get('/reddit', async (req, res) => {
const r = new snoowrap({
userAgent: process.env.user_agent,
clientId: process.env.client_id,
clientSecret: process.env.client_secret,
refreshToken: process.env.refresh_token
})
topPosts = []
;(await r.getHot()).forEach(post => {
topPosts.push({
title: post.title,
url: post.url
})
})
res.json(topPosts);
})
app.get('/news', async (req, res) => {
const news_url = 'https://www.theguardian.com/international'
axios(news_url)
.then(response => {
const html = response.data;
const $ = cheerio.load(html);
const articles = [];
const values = new Set();
$('.fc-item__title', html).each(function () { //<-- cannot be a function expression
const title = $(this).text().trim();
const url = $(this).find('a').attr('href');
if (!values.has(url)) {
values.add(url);
articles.push({
title,
url
});
}
})
res.json(articles)
}).catch(err => console.log(err))
})
app.listen(PORT, () => console.log(`Server is running on port ${PORT}`))```
Heroku runs on its own port, try setting port like this
const PORT = Number(process.env["PORT"]) || 8000

how to use async await on javascript frontend to receive data from async await node.js backend

In order to avoid cross origin issues, I've got a front end javascript that's querying a backend node.js server, which grabs data from an api on a different origin:
const API_URL = [SOME_OTHER_SERVER];
const API_TIMEOUT = 1000;
const API_TOKEN = [SOME_TOKEN]
const app = express();
const PORT = 3001;
app.use(cors());
app.get('/getBackendData', async(req, res)=> {
try {
const response = await axios.get(API_URL,{
timeout: API_TIMEOUT,
headers: {
'Authorization': `Token ${API_TOKEN}`,
'Access-Control-Allow-Origin': '*'
}
});
console.log(response.data.data); //this works to retrieve and log the data
return response.data.data; //I want this to return the data to the front end
} catch (error) {
console.error(error);
return error;
}
});
app.listen(PORT, function() {
console.log('backend listening on port %s.', PORT);
});
On the front end, I'm querying my node.js backend:
const BACKEND_API_URL = 'http://localhost:3001/getBackendData';
async function getData()
{
let response = await fetch(BACKEND_API_URL, {
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
}
});
let data = await response;
return data;
}
getData()
.then(data => console.log(data)); //does not log the data from the backend
What am I doing wrong that I can't get a response from my node.js backend on the frontend?
You don't can use return in express route.
use instead res object like this: res.send(response.data.data)
see: https://expressjs.com/pt-br/api.html#res

Get value from client side script and override server side script

Below are my server side and client side JavaScript files. I have hard coded queryObject in server side script I can display the body in client-side.
The problem is how to get value from client side for queryObject variable in server side and override the existing values.
In short, current program converts USD to GBP as I hard-coded it. I want a way to access queryObject from client side and give my own values.
//=====================Server Side Script========================//
var request = require('request');
const path = require("path");
const express = require("express");
const app = express();
// const hbs = require("hbs");
const port = process.env.PORT || 3000;
const pathPublic = path.join(__dirname, "../public");
const pathView = path.join(__dirname, "../templates/views");
app.set("view engine", "hbs");
app.set("views", pathView);
app.use(express.static(pathPublic));
app.get("", (req, res) => {
res.render("home", {
title: "Currency Converter"
});
});
app.get("/currency", (req, res) => {
const uri = "https://currency-exchange.p.rapidapi.com/exchange?",
headers={
'x-rapidapi-host': 'currency-exchange.p.rapidapi.com',
'x-rapidapi-key': 'b13c4f3d67msh8143a7f1298de7bp1e8586jsn4453f885a4e7'
}
const queryObject = {
q: 1,
from: 'USD',
to: 'GBP'
};
request({
url:uri,
qs:queryObject,
headers: headers
},
function (error, response, body) {
if (error) {
console.log('error:', error); // Print the error if one occurred
} else if(response && body) {
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
res.json({'body': body}); // Print JSON response.
}
})
});
app.listen(port, () => {
console.log("Server is running on port " + port);
});
//=====================Client Side Script========================//
const currency = document.querySelector("#currency");
const text1= document.querySelector(".text1");
const text2= document.querySelector(".text2");
const text3= document.querySelector(".text3");
const Form = document.querySelector("form");
function refreshPage() {
window.location.reload();
}
Form.addEventListener("submit", e => {
e.preventDefault();
fetch("http://localhost:3000/currency").then(response => {
response.json().then(data => {
if (data.error) {
console.log(data.error);
} else {
currency.textContent = data.body;
}
});
});
SOLUTION:
In order to modify any values in server, you have to send appropriate HTTP method (eg: POST) with appropriate data in it. And let the server handle the request to change the content of object to make an API call from there.
I made some changes in your code for demonstration and install 'cors', 'body-parser' module and other missing modules to make it run.
HTML:
<!DOCTYPE html>
<html>
<body>
<div id="currencyType">
<select id="fromCurrency">
<option value="USD">USD</option>
<option value="GBP">GBP</option>
</select>
<select id="toCurrency">
<option value="USD">USD</option>
<option value="GBP">GBP</option>
</select>
</div>
<button type="button" id="getCurrency">Get Currency</button>
<div id="currency" name="currency" type="text"></div>
<script>
const currency = document.querySelector("#currency");
const btn = document.getElementById("getCurrency");
function refreshPage() {
window.location.reload();
}
btn.addEventListener("click", e => {
var fromCurrency = document.getElementById("fromCurrency");
fromCurrency = fromCurrency.options[fromCurrency.selectedIndex].value;
var toCurrency = document.getElementById("toCurrency");
toCurrency = toCurrency.options[toCurrency.selectedIndex].value;
var data = {
fromCurrency: fromCurrency,
toCurrency: toCurrency
};
// calls the API with POST method with data in it
fetch("http://localhost:3000/currency", {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
}).then(response => {
response.json().then(data => {
if (data.error) {
console.log(data.error);
} else {
currency.textContent = "1 " + fromCurrency + " = " + data.body + " " + toCurrency;
}
});
});
});
</script>
</body>
</html>
NodeJS:
var request = require('request');
const path = require("path");
const express = require("express");
const app = express();
var cors = require('cors')
// const hbs = require("hbs");
var bodyParser = require('body-parser');
const port = process.env.PORT || 3000;
const pathPublic = path.join(__dirname, "public");
const pathView = path.join(__dirname, "templates/views");
app.set("view engine", "hbs");
app.set("views", pathView);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(pathPublic));
app.use(cors())
app.get("", (req, res) => {
res.render("home", {
title: "Currency Converter"
});
});
app.post("/currency", (req, res) => {
console.log(req.body);
const uri = "https://currency-exchange.p.rapidapi.com/exchange?",
headers={
'x-rapidapi-host': 'currency-exchange.p.rapidapi.com',
'x-rapidapi-key': 'b13c4f3d67msh8143a7f1298de7bp1e8586jsn4453f885a4e7'
}
const queryObject = {
q: 1,
from: req.body.fromCurrency,
to: req.body.toCurrency
};
console.log(queryObject);
request({
url:uri,
qs:queryObject,
headers: headers
}, function (error, response, body) {
if (error) {
console.log('error:', error); // Print the error if one occurred
} else if(response && body) {
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
res.json({'body': body}); // Print JSON response.
}
})
});
app.listen(port, () => {
console.log("Server is running on port " + port);
});
Sample output:
You'll code in client-side to send a request to server-side containing the query object.
And on the server-side, you pick up your query object.
There are so many ways of doing this.
Using a GET request with parameters - On the server-side your query object will be available at res.query.params
Using a POST request - On the server side you will want to use the body-parser plugin for parsing your response body and hence, your data will be available at res.body
Read on body parser

Web3 web3.eth.sendSignedTransaction Invalid params

Im very new to ethereum i have set up a private network using the pantheon client. i have successfully deployed a contract to the network and all interactions with the contract work when using through remix.
I am trying to set up a relay where a transaction is signed client side, sent to a nodeJs server and then the server proxies the transaction to the contract. however when i pass the signed transaction to sendSignedTransaction() i get the error Invalid params, to me this is very vague and i am unsure what i'm doing wrong / what the invalid params are. (any advice on how to debug this?)
UPDATE
using web3 v1.2.0
Error
Error: Returned error: Invalid params
at Object.ErrorResponse (/Users/ghost/node_modules/web3-core-helpers/src/errors.js:29:16)
at Object.<anonymous> (/Users/ghost/node_modules/web3-core-requestmanager/src/index.js:140:36)
at /Users/ghost/node_modules/web3-providers-ws/src/index.js:121:44
at Array.forEach (<anonymous>)
at W3CWebSocket.WebsocketProvider.connection.onmessage (/Users/ghost/node_modules/web3-providers-ws/src/index.js:98:36)
at W3CWebSocket._dispatchEvent [as dispatchEvent] (/Users/ghost/node_modules/yaeti/lib/EventTarget.js:107:17)
at W3CWebSocket.onMessage (/Users/ghost/node_modules/websocket/lib/W3CWebSocket.js:234:14)
at WebSocketConnection.<anonymous> (/Users/ghost/node_modules/websocket/lib/W3CWebSocket.js:205:19)
at WebSocketConnection.emit (events.js:188:13)
at WebSocketConnection.processFrame (/Users/ghost/node_modules/websocket/lib/WebSocketConnection.js:552:26)
at /Users/ghost/node_modules/websocket/lib/WebSocketConnection.js:321:40
at process.internalTickCallback (internal/process/next_tick.js:70:11)
Contract
pragma solidity ^0.5.1;
import "./Ownable.sol";
contract Entry is Ownable {
mapping (address => string) hash;
function addEntry(string memory _hash) public {
hash[msg.sender] = _hash;
}
function getHash() public view returns(string memory){
return hash[msg.sender];
}
}
Relay Server
const Web3 = require('web3');
const express = require('express')
const app = express()
const port = 3003
const bodyParser = require('body-parser');
const cors = require('cors')
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json())
app.use(cors())
var web3 = new Web3(Web3.givenProvider || "ws://localhost:7002");
app.post('/transaction/send', async (req, res) => {
const {tx, data} = req.body;
web3.eth.sendSignedTransaction(tx, function (err, transactionHash) {
if(err) console.log(err);
console.log(transactionHash);
});
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
Front end
import React from 'react';
import './App.css';
import Web3 from 'web3';
import request from 'request-promise';
const Tx = require('ethereumjs-tx').Transaction;
const web3 = new Web3("http://localhost:8545");
const privKey = '[My Priv key here]';
const contractADDRESS = "0x4261d524bc701da4ac49339e5f8b299977045ea5";
const addressFrom = '0x627306090abaB3A6e1400e9345bC60c78a8BEf57';
const contractABI = [{"constant":false,"inputs":[{"name":"_hash","type":"string"}],"name":"addEntry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getHash","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}];
function App() {
async function sendTx(){
const data = await extraData();
web3.eth.getTransactionCount(addressFrom).then(txCount => {
const txData = {
nonce: web3.utils.toHex(txCount),
gasLimit: web3.utils.toHex(25000),
gasPrice: web3.utils.toHex(10e9),
to: contractADDRESS,
from: addressFrom,
data: data
}
sendSigned(txData, function(err, result) {
if (err) return console.log('error', err)
console.log('sent', result)
})
})
}
async function sendSigned(txData, cb) {
const privateKey = new Buffer(privKey, 'hex')
const transaction = new Tx(txData)
transaction.sign(privateKey)
const serializedTx = transaction.serialize().toString('hex')
const response = request({
method: 'POST',
uri: 'http://127.0.0.1:3003/transaction/send',
body: {
tx: serializedTx,
data: 'somehashhh'
},
json: true,
});
}
async function extraData() {
const contractInstance = new web3.eth.Contract(contractABI, contractADDRESS);
return await contractInstance.methods.addEntry('somehashhh').encodeABI();
}
return (
<div className="App">
<header className="App-header">
<div onClick={() => sendTx()}>Submit transaction</div>
</header>
</div>
);
}
export default App;
This is the txData sent from front end
{
data: "0x17ce42bd0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a736f6d6568617368686800000000000000000000000000000000000000000000"
from: "0x627306090abaB3A6e1400e9345bC60c78a8BEf57"
gasLimit: "0x61a8"
gasPrice: "0x2540be400"
nonce: "0x0"
to: "0x4261d524bc701da4ac49339e5f8b299977045ea5"
}
After a lot of trail and error an 0 suggestions on stack overflow working, i have got the transaction signing working!. In the end i came away from using ethereumjs-tx (which for some reason is recommended by a lot of people) and used just pure Web3.
Front end client
async function sendTx(){
const { address: from } = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY)
const contract = new web3.eth.Contract(CONTRACT_ABI, CONTRACT_ADDRESS)
const query = await contract.methods.updateCount();
const signed = await web3.eth.accounts.signTransaction({
to: CONTRACT_ADDRESS,
from,
value: '0',
data: query.encodeABI(),
gasPrice: web3.utils.toWei('20', 'gwei'),
gas: Math.round((await query.estimateGas({ from })) * 1.5),
nonce: await web3.eth.getTransactionCount(from, 'pending')
}, PRIVATE_KEY)
const response = await request({
method: 'POST', json: true,
uri: 'http://127.0.0.1:3003/transaction/send',
body: {
tx: signed.rawTransaction,
data: 'some data'
}
});
console.log(response);
}
Relay Server
const Web3 = require('web3');
const express = require('express')
const app = express()
const port = 3003
const bodyParser = require('body-parser');
const cors = require('cors')
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json())
app.use(cors())
var web3 = new Web3(Web3.givenProvider || "ws://localhost:7002");
app.post('/transaction/send', async (req, res) => {
const {tx, data} = req.body;
web3.eth.sendSignedTransaction(tx)
.on('transactionHash', (txHash) => res.json({txHash}))
.on('error', console.log)
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
hopefully this can help someone else
👍

Categories