I need to make a POST request on my ExpressJS app... But i want to get the body results outside of the callback function in order to work with them...
I think I need a sync function...
var TOKEN;
exports.getToken = function(req, res){
var postData = {
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
grant_type: 'authorization_code',
redirect_uri: REDIRECT_URI,
code: CODE
}
var url = 'https://api.instagram.com/oauth/access_token';
// Make my sync POST here and get the TOKEN
// example :
// request.post({....}, function(err, res, body){ TOKEN = body; });
// console.log(TOKEN);
res.render('index', {title: '****'});
}
Look at the Async library. The series or waterfall functions are what you want.
https://github.com/caolan/async#waterfall
Something along these lines:
async.waterfall([
function (callback) {
var postData = {
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
grant_type: 'authorization_code',
redirect_uri: REDIRECT_URI,
code: CODE
}
var url = 'https://api.instagram.com/oauth/access_token';
//pass the body into the callback, which will be passed to the next function
request.post(postData, function (err, res, body) { callback(null,body); });
},
function (token, callback) {
//do something with token
console.log(token);
callback(null);
}
], function (err, result) {
// result now equals 'done'
res.render('index', { title: '****' });
});
Related
Using spotify-web-api-node I create AuthorizeURL which works fine, Its going to my callback, then I receive my token, and store it in cookie. But when Im trying to create some request with this token, I get error:
"{"error":{"status":401,"message":"Invalid access token"}}"
Am I missing something? Here is the following code:
// Create and redirect to AuthorizeURL
spotify.get("/spotify/login", async (req, res) => {
let scopes = ['user-read-currently-playing'],
responseType = 'token',
showDialog = true;
let localSpotifyApi = new SpotifyWebApi({
clientId: client_id,
redirectUri: redirect_uri
});
res.redirect(localSpotifyApi.createAuthorizeURL(
scopes,
showDialog,
responseType
));
});
// Handle the callback
spotify.get('/spotify/callback', async (req, res) => {
let access_token = req.query.code;
res.cookie('spotify_access_token', access_token, { maxAge: 3600000});
return res.redirect('/spotify/api/get-currently-playing');
});
// Trying to use stored access token somewhere later
spotify.get('/spotify/api/get-currently-playing', async (req, res) => {
let credentials = {
clientId: client_id,
clientSecret: client_secret,
accessToken: req.cookies.spotify_access_token
};
let localSpotifyApi = new SpotifyWebApi(credentials);
localSpotifyApi.getMyCurrentPlayingTrack()
.then(function(data) {
console.log(data);
return res.json(data);
}, function(err) {
console.log(err.message);
return res.json({'err' : err});
});
});
I created a middleware as below:
const oAuth = (req, res, next) => {
axios.post(tokenEndpoint, "", { params: {
grant_type: process.env.GRANT_TYPE,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
code: process.env.AUTHORIZATION_CODE,
}}).then(response => {
req.oAuth = response.data;
//console.log(response.data);
console.log(req.oAuth);
}).catch(err => {
console.error(err);
})
next();
}
module.exports = oAuth;
the response/result of the oauth function is something like:
{
access_token: '1000.ddf6d96b4f3sadasdasdas55a2450ae13',
refresh_token: '100dasdsadasdsadhgdhgfhdghdfghe427288',
api_domain: 'https://www.oapis.com',
token_type: 'Bearer',
expires_in: 3600
}
now in the "index.js" file I'm trying to destructure the oAuth function response object to access the attribute access_token and put it in the URL to make a post request, but I'm not succeeding. what am I doing wrong?
const express = require("express");
const axios = require("axios");
const oAuth = require("./oAuth.js");
const app = express();
app.use(oAuth);
var port = process.env.PORT || 3001;
const someAPI = "https://www.oapis.com/crm/v2/Leads";
app.get("/", async (req, res) => {
try {
const {access_token} = req.oAuth
const response = await axios({
method: "GET",
url: someAPI,
//timeout: 1000,
headers: { Authorization: `Zoho-oauthtoken ${access_token}` },
});
return res.json(response.data);
} catch (error) {
console.log(error);
if (error.response.status === 401) {
res.status(401).json("Unauthorized to access data");
} else if (error.response.status === 403) {
res.status(403).json("Permission denied");
} else {
res.status(500).json("Whoops. Something went wrong");
}
};
});
I would suggest using async/await here to wait for oauth response and only then modify request object in order to pass it further to the next() callback.
const oAuth = async (req, res, next) => {
try {
const response = axios.post(tokenEndpoint, "", { params: {
grant_type: process.env.GRANT_TYPE,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
code: process.env.AUTHORIZATION_CODE,
}});
console.log(response.data);
req.oAuth = response.data;
} catch (e) {
console.log(e);
}
next();
}
module.exports = oAuth;
I've been attempting to establish a simple Oauth2 flow using Node, Express, and Request, but I keep running into issues at the token request stage. In my specific example, I'm running an Oauth2 with MailChimp, but the problem persists with any platform.
In this example, after I post the code to get the token, I receive a response that tells me { error: 'invalid_request', error_description: 'Invalid grant_type parameter or parameter missing' }. That makes me think I'm not posting the data properly... I'm at the point that I'm convinced it's some core concept I'm missing in my logic. Any recommendations are appreciated.
Here's what I'm doing:
/* Redirect the user to MailChimp login */
app.get(`/login`, function (req, res) {
res.redirect(url.format({
pathname: 'https://login.mailchimp.com/oauth2/authorize/',
query: {
response_type: 'code',
client_id: client_id,
redirect_uri: 'http://127.0.0.1:3000/auth/'
}
}));
});
/* Recieve the code from MailChimp, and post it back to request a token */
app.get(`/auth`, function (req, res) {
request.post('https://login.mailchimp.com/oauth2/token', {
json: true,
gzip: true,
body: {
grant_type: 'authorization_code',
client_id: client_id,
client_secret: client_secret,
redirect_uri: 'http://127.0.0.1:3000/authed',
code: req.query.code,
},
}, function (err, response, body) {
console.log(response);
});
});
/* Success! We'll do something with the token here... */
app.post('/authed', function(req, res) {
res.send('we did it!')
});
I'm authenticating with the 23andMe API with OAuth 2. I'm able to receive the code after the user grants access. I'm currently trying to send a post request to receive the access token. I continue to receive this error:
data:
{ error_description: 'No grant_type provided.',
error: 'invalid_request' } }
I am using the axios package to make my post request. There is an error in my request because I got a successful 200 response and access token when I cuRL:
curl https://api.23andme.com/token/
-d client_id='zzz' \
-d client_secret='zzz' \
-d grant_type='authorization_code' \
-d code=zzz \
-d "redirect_uri=http://localhost:3000/receive_code/"
-d "scope=basic%20rszzz"
I'm able to receive the authorization code from the 23andMe server. I'm then redirected to my application. Here's my GET route:
router.get('/receive_code', function(req, res) {
axios.post('https://api.23andme.com/token/', {
client_id: zzz,
client_secret: zzz,
grant_type: 'authorization_code',
code: req.query.code,
redirect_uri: 'http://localhost:3000/receive_code/',
scope: "basic%20rs3094315"
}).then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});
});
Any thoughts?
The problem is the form key you've placed in your payload. It should work like this:
axios.post('https://api.23andme.com/token/', {
client_id: zzz,
client_secret: zzz,
grant_type: 'authorization_code',
code: req.query.code
redirect_uri: 'http://localhost:3000/receive_code/',
scope: "basic%20rs3094315"
}).then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});
I was able to solve the problem by using the simple-oauth2 npm package.
It can be found here: https://www.npmjs.com/package/simple-oauth2#express-and-github-example
// **********23ANDME OAUTH2************
var oauth2 = require('simple-oauth2')({
clientID: 'zzz',
clientSecret: 'zzz',
site: 'https://api.23andme.com',
tokenPath: '/token',
authorizationPath: '/authorize'
});
var authorization_uri = oauth2.authCode.authorizeURL({
redirect_uri: 'http://localhost:3000/receive_code/',
scope: 'basic analyses rs1234567',
state: 'jenvuece2a'
});
// *************************************
// In you view, place "/auth" in your <a> e.g. Click Me
router.get('/auth', function (req, res) {
res.redirect(authorization_uri);
});
router.get('/receive_code', function(req, res) {
var code = req.query.code;
if (!code) {
res.send('Error!!')
} else {
console.log('running');
oauth2.authCode.getToken({
code: code,
redirect_uri: 'http://localhost:3000/receive_code/'
}, saveToken);
function saveToken(error, result) {
if (error) {
console.log('Access Token Error', error.message);
} else {
token = oauth2.accessToken.create(result);
console.log(token);
}
};
res.render('/genetic_report', {layout: 'dash'});
}
});
I'm trying to get my refresh_token to generate a new access_token. I'm using the request module to make the request, but It's returning an error saying something along the lines of "Could not find page".
var request = require('request');
module.exports = function(callback){
console.log('here');
request('https://googleapis.com/oauth2/v3/token?client_id=NotID&client_secret=Not_Secret&refresh_token=NotRefresh&grant_type=refresh_token', function (error, response, body) {
if (!error && response.statusCode == 200) {
callback(response)
}
});
}
Try this:
request.post('https://accounts.google.com/o/oauth2/token', {
form: {
grant_type:'refresh_token',
refresh_token:'..',
client_id:'..',
client_secret:'..'
}
}, function (err, res, body) {})
This works..
const axios = require('axios');
const querystring = require('querystring');
const keys = require('../config/keys');
const getAccessToken = async refreshToken => {
try {
const accessTokenObj = await axios.post(
'https://www.googleapis.com/oauth2/v4/token',
querystring.stringify({
refresh_token: refreshToken,
client_id: keys.googleClientID,
client_secret: keys.googleClientSecret,
grant_type: 'refresh_token'
})
);
return accessTokenObj.data.access_token;
} catch (err) {
console.log(err);
}
};