how to use access token to call another post request? - node.js

I have this post request to get access token and its working fine but would like to know how can I use this access token to call another post request ? Or how do I use async or promises to use in this ?
Here is my code :
function getAccessToken() {
const querystring = require('querystring');
const https = require('https')
const postData = querystring.stringify({
'grant_type': 'client_credentials'
});
const options = {
"hostname":'api.xxx.com',
"method": "POST",
"path" : "/token",
"port" : 443,
"encoding": "utf8",
"followRedirect": true,
"headers": {
"Authorization": 'Basic ' + Buffer.from("client_id" + ':' + "client_secret").toString('base64'),
"Content-Type": 'application/x-www-form-urlencoded',
"Content-Length": Buffer.byteLength(postData),
},
'muteHttpExceptions': true
}
const body = []
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (chunk) => body.push(chunk))
res.on('end', () => {
const access_token = Buffer.concat(body).toString()
console.log(access_token)
})
})
req.on('error', error => {
console.error(error)
})
req.write(postData);
req.end()
}
getAccessToken();

You can save token in database,file or other memory database and use it in all requests in the Authorization header but depends on type of token,for example for set JWT token:
request.setHeader('Authorization', 'Bearer '+accessToken)
OR in option object:
options = {
host: '<URL>',
path: '<path of endpoint>',
port: '<portNumber>',
headers: {'Authorization', 'Bearer '+accessToken}
};
also for the async request to another endpoint, you can use Axios axios example:
const axios = require('axios').default;
const sendGetRequest = async () => {
try {
const resp = await
axios.get('https://jsonplaceholder.typicode.com/posts', {
headers: {
'authorization': 'Bearer YOUR_JWT_TOKEN_HERE'
}
});
console.log(resp.data);
} catch (err) {
// Handle Error Here
console.error(err);
}
};
sendGetRequest();

Related

Cannot save email in React.js + Express

So I have a function getProfile(). Inside it I am trying to fetch users from the server using a POST call, however it's throwing a CORS error in its response.
Here is the getProfile:
const getProfile = async () => {
try {
const res = await fetch("http://localhost:5000/dashboard/", {
method: "POST",
headers: {
jwt_token: localStorage.token,
"Content-Type": "application/json",
Accept: "application/json",
},
});
const parseData = await res.json();
setEmail(parseData.email);
console.log("Try success");
console.log(parseData.email);
} catch (err) {
console.log("Try failed");
console.error(err.message);
}
};
if you are handling your nodeServer by your own you need to add CORS package
please check this and follow their docs
https://www.npmjs.com/package/cors
1.install package
2. in your app.js file add following
var cors = require('cors')
app.use(cors())
and change you frontend function getProfile() to following:
const getProfile = async () => {
let token = localStorage.getItem("token");
const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", "bearer" + token);
try {
await fetch("http://localhost:5000/dashboard/", {
method: "POST",
headers: myHeaders,
})
.then((r) => r.json().then((data) => ({ status: r.status, data })))
.then((obj) => obj.status === 200 && console.log("data", obj.data));
} catch (err) {
console.error("Try failed", err.message);
}
};

Cannot send firebase push notification from lambda

I am hoping someone can help me point my mistake here.
I am trying to send a firebase push notification through a lambda using the HTTP legacy endpoint
https://fcm.googleapis.com/fcm/send
I am following the guide from:
https://craigrussell.io/2019/03/send-firebase-fcm-push-notification-from-aws-lambda/
Here is my code:
const authHeader ='key=A****IV';
const deviceToken ='eut4****pm';
console.log('sending Push notification');
return new Promise((resolve, reject) => {
const options = {
host: 'fcm.googleapis.com',
path: '/fcm/send',
method: 'POST',
headers: {
'Authorization': authHeader,
'Content-Type': 'application/json',
},
};
const req = http.request(options, (res) => {
console.log('success');
resolve('success');
});
req.on('error', (e) => {
console.log('failuree' + e.message);
reject(e.message);
});
// const reqBody = '{"to":"' + deviceToken + '", "priority" : "high"}';
const reqBody = '{"to":"' + deviceToken + '", "priority": "high", "notification": {"title": "Test", "body": "Test"}}';
console.log(reqBody);
req.write(reqBody);
req.end();
});
};
I do not receive any push notification after this . Am i doing something wrong here?
I think the key point is that you use the http module. Actually, it works well when using https module on my side.
var https = require('https');
The complete code is as follows:
var https = require('https');
exports.handler = async(event) => {
const authHeader = 'key=AA***y';
const deviceToken = 'fG***-';
return new Promise((resolve, reject) => {
const options = {
host: 'fcm.googleapis.com',
path: '/fcm/send',
method: 'POST',
headers: {
'Authorization': authHeader,
'Content-Type': 'application/json',
},
};
console.log(options);
const req = https.request(options, (res) => {
console.log('success');
console.log(res.statusCode);
resolve('success');
});
req.on('error', (e) => {
console.log('failuree' + e.message);
reject(e.message);
});
// const reqBody = '{"to":"' + deviceToken + '", "priority" : "high"}';
const reqBody = '{"to":"' + deviceToken + '", "priority": "high", "notification": {"title": "Test", "body": "Test"}}';
console.log(reqBody);
req.write(reqBody);
req.end();
});
};
For more details, you can see the res field after http request, it will show statusCode 403 when you use http.

Node.js https.request method using client credentials

I am trying to make a request for an access token using https.request but I keep getting the following error:
"error":"invalid_request","error_description":"Missing grant type"
In the Node.js HTTPS.Request documentation there isn't any reference for how to set the grant type. I believe I need to set it in the body of the request, but there is also no reference to attaching a body to the request. I am attempting to do it with the payload variable but obviously that isn't working. I am also trying to do this request with 0 or as little dependencies as possible.
function getAccessToken() {
const https = require('https')
const payload = {
"grant_type": "client_credentials"
}
const options = {
"hostname": url,
"method": "POST",
"path" : "/oauth2/token",
"port" : 443,
"encoding": "utf8",
"followRedirect": true,
"headers": {
"Authorization": "Basic <base64 encoded client_id:client_secret>",
"scope": "PARTNER_READ"
},
"payload": payload,
'muteHttpExceptions': true
}
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', d => {
process.stdout.write(d)
})
})
req.on('error', error => {
console.error(error)
})
req.end()
}
Any help would be appreciated!
Just to close the loop on this, I was missing the 'Content-Type' in the header which I think was causing the "Missing Grant Type" error because it couldn't parse the body. I also needed to write the postData to the request right before the req.end(). So thank you #Klaycon for that point in the right direction!
Here is my updated code:
function getAccessToken() {
const querystring = require('querystring');
const https = require('https')
const postData = querystring.stringify({
'grant_type': 'client_credentials'
});
const options = {
"hostname": url,
"method": "POST",
"path" : "/oauth2/token",
"port" : 443,
"encoding": "utf8",
"followRedirect": true,
"headers": {
"Authorization": "Basic <base64 encoded client_id:client_secret>",
"Content-Type": 'application/x-www-form-urlencoded',
"Content-Length": Buffer.byteLength(postData),
},
'muteHttpExceptions': true
}
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', d => {
process.stdout.write(d)
})
})
req.on('error', error => {
console.error(error)
})
req.write(postData);
req.end()
}

How can I get Axios to send a request with FormData?

I'm unable to get the server that I'm calling to recognize the FormData that I'm providing when I use axios. It keeps telling me that I'm not providing the right FormData even though it works in Postman and Node native http (see below):
import { Router } from "express";
import axios from "axios";
import * as FormData from "form-data";
const router = Router();
const cookieHeader = {
Cookie: "XXX",
};
router.get("/", async (_req, res) => {
try {
const formData = new FormData();
formData.append("key1", JSON.stringify(["value1"]));
formData.append("key2", "value2");
formData.append("key3", "value3");
const response = await axios.post("https://xxx", formData, { headers: { "Content-Type": "multipart/form-data; boundary=--------------------------811161660471543283806813" } });
res.send(response.data);
} catch (error) {
console.log(error);
}
});
module.exports = router;
I am able to get it working in Postman and used that to export using Node's native http, which also works:
import { Router } from "express";
import { https } from "follow-redirects";
const router = Router();
router.get("/", () => {
const options = {
method: "POST",
hostname: "xxx",
path: "/xx/xxx",
headers: {
"Content-Type": "multipart/form-data; boundary=--------------------------811161660471543283806813",
Cookie: "xxx",
},
maxRedirects: 20,
};
const req = https.request(options, (res: any) => {
const chunks: any[] = [];
res.on("data", (chunk: any) => {
chunks.push(chunk);
});
res.on("end", () => {
const body = Buffer.concat(chunks);
console.log(body.toString());
});
res.on("error", (error: any) => {
console.error(error);
});
});
const postData = `------WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"key1\"\n\n[\"value1\"]\n------WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"key2\"\n\nvalue2\n------WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"key3\"\n\nvalue3\n------WebKitFormBoundary7MA4YWxkTrZu0gW--`;
req.setHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
req.write(postData);
req.end();
});
module.exports = router;
I figured it out after reading through https://github.com/axios/axios/issues/318. It wasn't until near the end that Googrosh posted that he used .getHeaders(). Lo and behold, I added that to my headers too and it worked.
So updating my code, here's what it looks like:
const response = await axios.post("https://xxx", formData, { headers: formData.getHeaders() });
onst formUrlEncoded = x =>
Object.keys(x).reduce((p, c) => p + `&${c}=${encodeURIComponent(x[c])}`, '')
var axios = require("axios");
axios({
url: 'https://login.xyz.com/oauth/v2/token',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: formUrlEncoded({
client_id: '***',
client_secret: '***',
grant_type: 'authorization_code',
})
})
.then(function(response) {
console.log(response.data)
})
.catch(function(error) {
console.log(error)
})

How do you make this curl request in node

This curl request to the spotify API works perfectly fine
curl -X "POST" -H "Authorization: Basic <my-key-here>" -d grant_type=client_credentials https://accounts.spotify.com/api/token
I'm trying to do this in node, but it's not working and returns a 400 Bad Request. Here is my code. What am I doing wrong?
function AuthRequest(key) {
const req_body_params = JSON.stringify({
grant_type: "client_credentials"
})
const base64_enc = new Buffer(key).toString("base64")
const options = {
host: "accounts.spotify.com",
port: 443,
path: "api/token",
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${base64_enc}`
}
}
const req = https.request(options, function (res) {
res.on('data', function (data) {
alert("success: " + data)
})
})
req.on('error', function (err) {
alert("error: " + err)
})
req.write(req_body_params)
req.end()
}
I'm trying to use the Client Credentials method as explained here: https://developer.spotify.com/web-api/authorization-guide/
The request should be in application/x-www-form-urlencoded instead of JSON, it should be const req_body_params = "grant_type=client_credentials" with a header of "Content-Type": "application/x-www-form-urlencoded"
function AuthRequest(key) {
const req_body_params = "grant_type=client_credentials";
const base64_enc = new Buffer(key).toString("base64");
const options = {
host: "accounts.spotify.com",
port: 443,
path: "/api/token",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": `Basic ${base64_enc}`
}
};
const req = https.request(options, function(res) {
res.on('data', function(data) {
alert("success: " + data)
})
});
req.on('error', function(err) {
alert("error: " + err)
});
req.write(req_body_params);
req.end();
}
Because token expires is good to request them dynamically, I created a method that output a token as a promise, then you can consume in your request.
const axios = require('axios')
const client_id = process.env.SPOTIFY_CLIENT_ID;
const client_secret = process.env.SPOTIFY_CLIENT_SECRET;
function getToken( ) {
return axios({
url: 'https://accounts.spotify.com/api/token',
method: 'post',
params: {
grant_type: 'client_credentials'
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
auth: {
username: client_id,
password: client_secret
}
})
}
async function getSpotifyData( endpoint ){
const tokenData = await getToken( );
const token = tokenData.data.access_token;
axios({
url: `https://api.spotify.com/v1/${endpoint}`,
method: 'get',
headers: {
'Authorization': 'Bearer ' + token
}
}).then( response => {
console.log( response.data );
return response.data;
}).catch( error => {
throw new Error(error);
});
}
getSpotifyData( 'browse/new-releases' );

Resources