Google OAuth getting new access token with refresh token - node.js

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

Related

Destructuring assignment object from a middleware response

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;

node - How do I save the token returned by the POST request into a variable

I need to be able to save the token returned by the POST request so I can decode it and send it back with my other requests. I can only console log the token but could find no way of saving it to a variable. How do I go about doing this? Am I thinking of this problem all wrong?
const request = require('request');
const options = { method: 'POST',
url: process.env.AUTH_URL,
headers:
{ 'cache-control': 'no-cache',
'content-type': 'application/json',
api_key: process.env.API_KEY,
client_secret: process.env.CLIENT_SECRET,
client_id: process.env.CLIENT_ID },
body: { userName: process.env.USERNAME, userPassword: process.env.PASSWORD },
json: true };
async function authenticate(options) {
try{
console.log('inside try');
const reqToken = await request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body.token);
});
} catch(error) {
throw(error);
}
}
Either promisify the request or simply use axios which supports promise out of the box.
async function authenticate(options) {
try {
console.log("inside try");
const reqToken = await new Promise((res, rej) => {
request(options, function(error, response, body) {
if (error) rej(error);
res(body.token);
});
});
} catch (error) {
throw error;
}
}
OR using axios:
async function authenticate(options) {
try {
console.log("inside try");
const { data:{ token } } = await axios(options);
} catch (error) {
throw error;
}
}

How to receive query in node js

After authorization through spotify web api in node I redirect to another page with url: http://localhost:8888/homepage#access_token=....
so I want to take the access token on that page and fetch data but when I use req.query I receive an empty object. Is there something wrong? How can I get that access token?
request.post(authOptions, (error, response, body) => {
if (!error && response.statusCode === 200) {
const access_token = body.access_token;
const refresh_token = body.refresh_token;
const options = {
url: "https://api.spotify.com/v1/me",
headers: { Authorization: `Bearer ${access_token}` },
json: true
};
request.get(options, (error, response, body) => {
console.log(body);
});
res.redirect(
"/homepage#" +
querystring.stringify({
access_token: access_token,
refresh_token: refresh_token
})
);
const express = require("express");
const router = express.Router();
router.get("/", (req, res) => {
res.render("index/welcome");
});
router.get("/homepage", (req, res) => {
res.render("index/homepage");
console.log(req.query);
});
module.exports = router;
You're passing the token via a fragment instead of query parameters, aren't you?
const url = require('url');
res.redirect(url.format({
pathname:"/homepage",
query: {
"access_token": access_token,
"refresh_token": refresh_token
}
}));
Working with fragments is for client side handling only, it should never reach the server.

Export function and call it from a different file

I'm trying to export the below function and call it on a different file. It half-works. For example: If I call the function from the same file, it does save the data to the DB. However, If I call the function from a different file, it does not save it.
Token.js:
var express = require("express");
var router = express.Router();
var User = require("../models/user");
var request = require("request");
var refresh = function() {
request.post(
{
headers: {
"Content-Type": "api",
Authorization:
"auth"
},
url: "token",
form: {
grant_type: "refresh_token",
refresh_token:
"token"
}
},
function(error, response, body) {
var token = JSON.parse(body);
// res.send(token);
User.findOneAndUpdate(
{ user: 2 },
{ token: token.access_token },
{ upsert: true },
function(err, data) {
if (err) throw err;
console.log("Saved!");
}
).catch(error => {
console.log(error);
});
}
);
};
module.exports = refresh;
call.js
var refreshToken = require("./helpers/refresh-token");
refreshToken();
Edit: Fixed... I forgot to include call.js in app.js
Thank you

Make a post request with ExpressJS

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: '****' });
});

Resources