Application hanging after calling route? - javascript

I am trying to build a plugin to connect to my Freshbooks account through their API. I've managed to set up my connection to the API, but as soon as I make my request (I can see the "Made the request!" in console) the application the application just hangs. I can see in the console that my request is made but then nothing happens. Is it still waiting for the response?
Here is the code I am trying to use:
router.get("/", function(req, res) {
res.render("landing");
});
//setup the parameters for connecting to freshbooks api using simple-oauth2 library
const oauth2 = simpleOauthModule.create({
client: {
id: process.env.FRESHBOOKS_CLIENT_ID,
secret: process.env.FRESHBOOKS_CLIENT_SECRET,
},
auth: {
tokenHost: config.freshbooks.token_host,
tokenPath: config.freshbooks.toke_path,
authorizePath: config.freshbooks.authorize_path,
},
options: {
bodyFormat: 'json',
authorizationMethod: 'body',
},
});
//authorization uri definition
const authorizationUri = oauth2.authorizationCode.authorizeURL({
redirect_uri: 'https://localhost/callback'
});
//initial page redirecting to freshbooks
router.get('/auth', function(req, res) {
//console.log('--DEBUG-- Inside /auth');
console.log('--DEBUG-- Authorization URI: ' + authorizationUri);
res.redirect(authorizationUri);
});
//callback service parsing the authorization token and asking for access token
// router.get('/callback', async (req, res) => {
router.get('/callback', function(req, res) {
//console.log('--DEBUG-- Inside /freshbooks');
//const code = req.query.code;
//set the authorization code into the environment variables
config.freshbooks.auth_code = req.query.code;
console.log('--DEBUG-- Authorization Code: ' + config.freshbooks.auth_code);
//set the specific headers required by freshbooks as per documentation
var headers = {
'Api-version': 'alpha',
'Content-Type': 'application/json',
'Authorization': 'Bearer'
};
//set the data needed for getting token from freshbooks api
var data = {
grant_type: 'authorization_code',
client_id: process.env.FRESHBOOKS_CLIENT_ID,
client_secret: process.env.FRESHBOOKS_CLIENT_SECRET,
code: config.freshbooks.auth_code,
redirect_uri: 'https://localhost/callback'
};
//set the options for the request to get token
var options = {
url: config.freshbooks.token_host + config.freshbooks.token_path,
headers: headers,
method: 'GET',
body: JSON.stringify(data)
};
function callback(error, response, body) {
console.log('--DEBUG-- Made the request!');
if (!error && !(res.statusCode >= 200 && res.statusCode < 300)) {
console.log('--DEBUG-- Authorization Token Response: ' + data);
//set the access and refresh tokens in the environment variables
var tokens = JSON.parse(body);
config.freshbooks.access_token = tokens.access_token;
config.freshbooks.refresh_token = tokens.refresh_token;
} else {
error = new Error('--HTTP Error-- Authorization Token: ' + res.statusCode + ': ' + body);
}
}
//request access token from freshbooks api
request(options, callback);
});
Thanks for the help!

Related

How can I write a txt file in React?

I have a issue. I'm doing a project with React. My project is simply for listening to music on Spotify. It is necessary to train the code of the room entered from the home page to the url extension that I will use for Spotify. The api link I use for Spotify uses node.js, so it allows file reading, but I want it to write the code of the room I clicked in React at that time into that txt file. How can I do that?
My only wish is to save the room.id variable in the homepage file into the txt file in another way.
Example of homepage.js
<Heading as="h1" mb={6}>
Rooms
</Heading>
<Divider orientation="horizontal" />
{rooms.map((room)=> (
<ListItem>
<ListItemText primary={room.roomName} secondary={room.roomInfo}/>
{/* <Link to={`/room/${room.id}`}></Link> */}
<Link to={`/room/${room.id}`}>
<Button>
Join Room
</Button>
</Link>
</ListItem>))}
Example of Spotify redirect code..
/**
* This is an example of a basic node.js script that performs
* the Authorization Code oAuth2 flow to authenticate against
* the Spotify Accounts.
*
* For more information, read
* https://developer.spotify.com/web-api/authorization-guide/#authorization_code_flow
*/
var express = require('express'); // Express web server framework
var request = require('request'); // "Request" library
var cors = require('cors');
var querystring = require('querystring');
var cookieParser = require('cookie-parser');
/**
* Generates a random string containing numbers and letters
* #param {number} length The length of the string
* #return {string} The generated string
*/
var generateRandomString = function(length) {
var text = '';
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < length; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
};
var stateKey = 'spotify_auth_state';
var app = express();
app.use(express.static(__dirname + '/public'))
.use(cors())
.use(cookieParser());
app.get('/login', function(req, res) {
var state = generateRandomString(16);
res.cookie(stateKey, state);
// your application requests authorization
var scope = 'user-read-private user-read-email user-read-playback-state user-modify-playback-state user-read-currently-playing';
res.redirect('https://accounts.spotify.com/authorize?' +
querystring.stringify({
response_type: 'code',
client_id: client_id,
scope: scope,
redirect_uri: redirect_uri,
state: state
}));
});
app.get('/callback', function(req, res) {
// your application requests refresh and access tokens
// after checking the state parameter
var code = req.query.code || null;
var state = req.query.state || null;
var storedState = req.cookies ? req.cookies[stateKey] : null;
if (state === null || state !== storedState) {
res.redirect('/#' +
querystring.stringify({
error: 'state_mismatch'
}));
} else {
res.clearCookie(stateKey);
var authOptions = {
url: 'https://accounts.spotify.com/api/token',
form: {
code: code,
redirect_uri: redirect_uri,
grant_type: 'authorization_code'
},
headers: {
'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64'))
},
json: true
};
request.post(authOptions, function(error, response, body) {
if (!error && response.statusCode === 200) {
var access_token = body.access_token,
refresh_token = body.refresh_token;
var options = {
url: 'https://api.spotify.com/v1/me',
headers: { 'Authorization': 'Bearer ' + access_token },
json: true
};
// use the access token to access the Spotify Web API
request.get(options, function(error, response, body) {
console.log(body);
});
var fs = require('fs');
var roomCodeTxt = fs.readFileSync('roomCodeText.txt', 'utf-8');
// we can also pass the token to the browser to make requests from there
res.redirect(`http://localhost:3000/room/${roomCodeTxt}\#` +
querystring.stringify({
access_token: access_token,
refresh_token: refresh_token
}));
} else {
res.redirect('/#' +
querystring.stringify({
error: 'invalid_token'
}));
}
});
}
});
app.get('/refresh_token', function(req, res) {
// requesting access token from refresh token
var refresh_token = req.query.refresh_token;
var authOptions = {
url: 'https://accounts.spotify.com/api/token',
headers: { 'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64')) },
form: {
grant_type: 'refresh_token',
refresh_token: refresh_token
},
json: true
};
request.post(authOptions, function(error, response, body) {
if (!error && response.statusCode === 200) {
var access_token = body.access_token;
res.send({
'access_token': access_token
});
}
});
});
console.log('Listening on 8888');
app.listen(8888);
You can write to a file in node also. See fs.writeFileSync (because this is a server, fs.writeFile or fs.promises.writeFile would help with performance, but for something this little, it shouldn't really matter).
The basic idea is in node, when the user clicks your button, you'll send a request to your server to write a file. Something roughly like this:
// Using the native fetch API
const joinRoom = roomId => {
return fetch('/write/to/file/endpoint', {
body: JSON.stringify({ roomId: roomId }),
// This header lets the server know that what you're sending is JSON
headers: { 'Content-Type': 'application/json' },
method: 'POST'
})
}
// With axios (Added this example in reponse to the O.P.'s comment)
const joinRoom = roomId => {
// Axios will add the Content-Type: application/json header by default
return axios.post('/write/to/file/endpoint', { roomId: roomId })
}
...
<button onClick={() => joinRoom(room.id)}>Join Room</button
In your server, you just need to handle requests to this new endpoint and call fs.writeFileSync('roomCodeText.txt', roomId, 'utf-8'). The specific details for how this works depends on how you're handling requests (in vanilla node? With the express library?) You can refer to this stackoverflow question on how to retrieve a POST body in node. There's answers for both express and node. The specific answer I linked to explains how to do it with vanilla node. It assumed that url-encoded data was send in the POST body. We're sending JSON in the above example, so you just need to take that code snippet and replace qs.parse(body) with JSON.parse(body).

Azure AD publisher's authorization token request returned 302

In an Azure Function as a backend for my webpage, I requested an Azure AD publisher's authorization token as per this page instructed.
This is the line of codes of my Azure Functions:
// Stringfy request body
const postData = querystring.stringify({
'grant_type': 'client_credentials',
'client_id': client_id,
'client_secret': client_secret,
'resource': resource,
});
// Initiate options
var httpAgent = new http.Agent();
httpAgent.maxSockets = 200;
const options = {
hostname: 'login.microsoftonline.com',
path: `/${tenantId}/oauth2/token`,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
agent: httpAgent,
}
const tokenReq = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf-8')
res.on('data', (chunk) => {
console.log(chunk);
body += chunk;
});
res.on('end', () => {
console.log('No more data in response.');
console.log("body:" + body);
context.res = {
status: 200,
body: body,
};
});
});
tokenReq.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
context.res = {
status: 500,
body: `problem with request: ${e.message}`,
}
});
// write data to request body
tokenReq.write(postData);
tokenReq.end();
The expected response was the access token that I require, however running it locally I got STATUS 302, and a header containing a location and some other parameters, as a response. In my understanding STATUS 302 states that the URL is moved temporarily to the location provided in the header. Now, I don't know what I'm supposed to do, the request that I have to make is supposed to be a POST request so a redirection would not work. I've also tried to make a new request after receiving the redirect URL, but I got an error message saying: getaddrinfo ENOTFOUND {redirect URL from header}. What did I do wrong here?
The 302 error was caused by http module, you use require('http'); and http.request(options, (res).... to do the request, so it shows 302 error.
I suggest you to use var request = require('request'); to do the request, below is my function code for your reference (before use request module, you need to run npm install request to install it first):
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
var result = await generatetoken(context);
context.res = {
body: result
};
}
function generatetoken(context){
var request = require('request');
var options = {
'method': 'POST',
'url': 'https://login.microsoftonline.com/<your tenant id>/oauth2/token',
'headers': {
'Content-Type': 'application/x-www-url-form-urlencoded'
},
form: {
'client_id': 'xxxxxx',
'grant_type': 'client_credentials',
'resource': 'xxxxx',
'client_secret': 'xxxxx'
}
};
return new Promise(function(resolve, reject) {
request(options, function(err, res) {
if (err) {
reject(err);
} else {
context.log(res.body);
resolve(res.body);
}
})
})
}

How to disable multiple http(s) request using request package in node js?

I'm trying to request an API using nodejs request package. In order to use the API, i need to request a refresh token API and it will provide me both new refresh token and access token.So what I've done, I request the balance with request API if failed due to stat_code == 904 then I request for the new token and write it into a file.
Once the current access token expired I'll need to request a new access token with previous given refresh token. So when i trigger the request refresh token, there are multiple request within a second. The refresh token is changing once there a refresh token request coming into the API server.
I've done couple of research regarding this problem, the only closes thing that i found is in https://groups.google.com/forum/#!topic/nodejs/kleeRbjiioQ and i have implement the solution which mark the agent:false but still having the same issue.I use process.hrtime() for easy time referrer.
var fs = require("fs");
var cheerio = require('cheerio');
var request = require('request');
var async = require('async');
var username = '';
request_api('john');
//request api function
function request_api(username){
var username = username;
var acc_token = fs.readFileSync('authentication/acc_token', 'utf8').replace(/[\n\r]/g, '');
var datetime = process.hrtime()
console.log('request balance start '+ datetime)
console.log('username ='+username);
console.log('Access token ='+acc_token);
request({
url: 'https://sample.api/accbalance?', //URL to hit
qs: {username:username, channel:'WEB'}, //Query string data
method: 'GET',
json: true,
agent: false,
pool: false,
forever: false,
headers: {
'Authorization': 'Bearer '+ acc_token ,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
}, function (error, response, body) {
var $ = cheerio.load(body, { xmlMode: true });
var stat_code = $('ams\\:code').html();
//Check for error
if(error){
return console.log('Error:', error);
}
//Check for right status code
else if(response.statusCode == 401 && stat_code == 904){
//904 response timeout
console.log('status code '+response.statusCode+ ' and status code'+ stat_code)
async.waterfall([
request_token,
request_api(username)
], function (error) {
if (error) {
//handle readFile error or processFile error here
}
});
}
else {
console.log('This is your balance' +body.content.pps.balance);
console.log('This is your expiry date' +body.content.pps.activestop);
}
}
)
};
//request for API refresh token
function request_token(){
var scope = 'SANDBOX'
var consumer_key = 'key'
var consumer_secret = 'secret'
var en_auth_code = new Buffer(consumer_key + ':' + consumer_secret).toString('base64');
var ref_token = fs.readFileSync('authentication/ref_token', 'utf8').replace(/[\n\r]/g, '');
var datetime = process.hrtime()
console.log('request refresh token start '+ datetime)
console.log('refresh token = '+ ref_token)
request({
url: 'https://sample.api/token?', //URL to hit
qs: {grant_type:'refresh_token', refresh_token:ref_token ,scope:scope }, //Query string data
method: 'POST',
json: true,
agent: false,
pool: false,
headers: {
'Authorization': 'Basic '+ en_auth_code,
'Content-Type': 'application/x-www-form-urlencoded'
},
}, function(error, response, body){
if(error) {
console.log(error);
} else if(response.statusCode == 200){
console.log(response.statusCode, body);
fs.writeFileSync('authentication/acc_token', body.access_token, 'utf8', (err) => {
if (err) throw err;
});
console.log('Access token is saved! '+ body.access_token);
fs.writeFileSync('authentication/ref_token', body.refresh_token, 'utf8', (err) => {
if (err) throw err;
});
console.log('Refresh token is saved! '+ body.refresh_token);
} else {
console.log(response.statusCode+'\n'+body)
}
});
};
the output that I've received after running the code was something like this
request balance start 411093,450855461 //1st api request
username =john
Access token =b212ae55ea6cbb35421679e75f91b0
status code 401 and status code900904
request balance start 411093,814554860 //2nd api request suddenly trigger
username =john
Access token =b212ae55ea6cbb35421679e75f91b0
request refresh token start 411093,816874643
refresh token = 9e52f688428e3c8e8a1a0bb81e48182
200 { expires_in: 86400,
refresh_token: '7add853045e2d2534e4679d9d719eef9',
access_token: '414a4d7f2ca9f337a39f8ad2bc412b4' }
Access token is saved! 414a4d7f2ca9f337a39f8ad2bc412b4
Refresh token is saved! 7add853045e2d2534e4679d9d719eef9
status code 401 and status code900904
request balance start 411093,884380787
username =john
Access token =414a4d7f2ca9f337a39f8ad2bc412b4
request refresh token start 411093,885204220
refresh token = 7add853045e2d2534e4679d9d719eef9
200 {
expires_in: 86400,
refresh_token: '68798d3d73b7359b8463d8174ae63',
access_token: '6cfe65873cf2d46c99616360a76e34ef' }
Access token is saved! 6cfe65873cf2d46c99616360a76e34ef
Refresh token is saved! 68798d3d73b7359b8463d8174ae63
status code 401 and status code900904
request balance start 411093,986352118
username =john
Access token =6cfe65873cf2d46c99616360a76e34ef
request refresh token start 411093,987246880
refresh token = 68798d3d73b7359b8463d8174ae63
200 {
expires_in: 86400,
refresh_token: 'ec4758d42bc960d05cec7174da502764',
access_token: '2cc27b78c59267f7dee5ac1aed89c7a' }
Access token is saved! 2cc27b78c59267f7dee5ac1aed89c7a
Refresh token is saved! ec4758d42bc960d05cec7174da502764
status code 401 and status code900904
request balance start 411094,154365494
username =john
Access token =2cc27b78c59267f7dee5ac1aed89c7a
request refresh token start 411094,154877335
refresh token = ec4758d42bc960d05cec7174da502764
200 {
expires_in: 86400,
refresh_token: '50a160aceeac3e251d7e287b99ffa',
access_token: 'fddb51934f5d7de38a8469aefc23' }
Access token is saved! fddb51934f5d7de38a8469aefc23
Refresh token is saved! 50a160aceeac3e251d7e287b99ffa
status code 401 and status code900904
request balance start 411094,248689543
username =john
Access token =fddb51934f5d7de38a8469aefc23
request refresh token start 411094,253453940
refresh token = 50a160aceeac3e251d7e287b99ffa
200 {
expires_in: 86400,
refresh_token: 'd3123ac463e754afd41c7a7065f4b9fa',
access_token: 'adec764091897b591aecfa3db6d44cc' }
Access token is saved! adec764091897b591aecfa3db6d44cc
Refresh token is saved! d3123ac463e754afd41c7a7065f4b9fa
status code 401 and status code900904
request balance start 411094,392741956
username =john
Access token =adec764091897b591aecfa3db6d44cc
request refresh token start 411094,393600819
refresh token = d3123ac463e754afd41c7a7065f4b9fa
200 {
expires_in: 86400,
refresh_token: 'dfdb3434f4993da5e271570b994d126',
access_token: '6e53e9746ea9df7a5633f8e96923d5' }
Access token is saved! 6e53e9746ea9df7a5633f8e96923d5
Refresh token is saved! dfdb3434f4993da5e271570b994d126
status code 401 and status code900904
request balance start 411094,478962663
username =john
Access token =6e53e9746ea9df7a5633f8e96923d5
request refresh token start 411094,479420015
refresh token = dfdb3434f4993da5e271570b994d126
200 {
expires_in: 86400,
refresh_token: '5f137193cdac6e2ec13fe38daf6eba70',
access_token: '96687f1eb16094d53ee08abe1d5d40db' }
Access token is saved! 96687f1eb16094d53ee08abe1d5d40db
Refresh token is saved! 5f137193cdac6e2ec13fe38daf6eba70
This is your prepaid 1329438
This is your expiry date 20180313
It seems that the synchronous function got mix up I guess. Btw I'm trying to implement this in the server side. The feedback of the body api server would be in json file as shown below.
{
"resCode": "200",
"resDesc": "Operation successfully.",
"content": {
"pps": {
"balance": "1440198",
"activestop": "20180313"
},
"paid": "0"
}
}
the success refresh token body would be in json file as shown in below code.
{
"expires_in": 86400,
"refresh_token": "55379e18b6c6ce1ca6b39a77f15549a3",
"access_token": "7c6af5939cbecd7ccd83acf57b40bb"
}
Appreciate your help on this.
After almost a week of trying, I decide to change my code from using request package to using request-promise and it work!! So far I don't have multiple request to the API server and the code works fine. So i just wanted to share the code and hopefully it can help other people too.
var fs = require("fs");
var cheerio = require('cheerio');
var request = require('request-promise');
request_api_promise('john')
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
})
//request for API feature
function request_api_promise(username) {
let acc_token = fs.readFileSync('authentication/acc_token', 'utf8').replace(/[\n\r]/g, '');
let datetime = process.hrtime() //Calculate time start
console.log('request balance start =' + datetime)
console.log('username =' + username);
console.log('Access token =' + acc_token);
let option = {
url: 'https://sample.api/accbalance?', //URL to hit
qs: {
username: username,
channel: 'WEB'
}, //Query string data
method: 'GET',
json: true,
agent: false,
pool: false,
forever: false,
headers: {
'Authorization': 'Bearer ' + acc_token,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
resolveWithFullResponse: true
}
return request(option)
.then((response) => {
return ({
balance: response.body.content.pps.balance,
expiry_date: response.body.content.pps.activestop
})
})
.catch((error) => {
let $ = cheerio.load(error.response.body, {
xmlMode: true
});
let stat_code = $('ams\\:code').html();
if (error.statusCode == 401 && stat_code == 904) {
console.log('Error: status code ' + error.statusCode + ' stat_code code ' + stat_code)
return request_token_promise().then(() => request_api_promise(username))
}
console.log(error)
})
}
//request for API refresh token
function request_token_promise() {
let scope = 'SANDBOX'
let consumer_key = 'key'
let consumer_secret = 'secret'
let en_auth_code = new Buffer(consumer_key + ':' + consumer_secret).toString('base64');
let ref_token = fs.readFileSync('authentication/ref_token', 'utf8').replace(/[\n\r]/g, '');
let datetime = process.hrtime()
console.log('request refresh token start = ' + datetime)
console.log('refresh token = ' + ref_token)
let option = {
url: 'https://sample.api/token?', //URL to hit
qs: {
grant_type: 'refresh_token',
refresh_token: ref_token,
scope: scope
}, //Query string data
method: 'POST',
json: true,
agent: false,
pool: false,
headers: {
'Authorization': 'Basic ' + en_auth_code,
'Content-Type': 'application/x-www-form-urlencoded'
},
resolveWithFullResponse: true
}
return request(option)
.then((response) => {
if (response.statusCode == 200) {
console.log(response.statusCode);
console.log(response.body);
fs.writeFileSync('authentication/acc_token', response.body.access_token, 'utf8', (err) => {
if (err) throw err;
});
console.log('Access token is saved! ' + response.body.access_token);
fs.writeFileSync('authentication/ref_token', response.body.refresh_token, 'utf8', (err) => {
if (err) throw err;
});
console.log('Refresh token is saved! ' + response.body.refresh_token);
} else {
console.log(response.statusCode);
console.log(response.body);
}
})
};
below are the output.
request balance start =849919,250316580
username =john
Access token =8d729facf8cc22fa7ad676c7699d2
status code 401 anderrorus code 904
request refresh token start = 849919,417863982
refresh token = c4e674d0a68ba39f29f476b18bc5ed
200
{
expires_in: 86400,
refresh_token: '7c82da4ed9e6fb593e6fadd0c9fd30da',
access_token: '968472961db5274852afcee7431ed3f5' }
Access token is saved! 968472961db5274852afcee7431ed3f5
Refresh token is saved! 7c82da4ed9e6fb593e6fadd0c9fd30da
request balance start =849919,503441510
username =john
Access token =968472961db5274852afcee7431ed3f5
{ balance: '1329438', expiry_date: '20180313' }
But still I do know what wrong with the first set of code. Would be good if you guys can point the problem of my 1st code.

Getting 403 Forbidden on user_timeline but not on any other API

Using API auth
var oauth2 = new OAuth2('Consumer Key', 'Consumer Secret', 'https://api.twitter.com/', null, 'oauth2/token', null);
oauth2.getOAuthAccessToken('', 'grant_type': 'client_credentials' }, function (e, access_token) {
console.log(access_token); //string that we can use to authenticate request
requestURL = {
url: 'https://api.twitter.com/1.1/statuses/user_timeline?user_id=' + userid,
headers: {
Authorization: 'Bearer ' + access_token
}
};
request(URL, function(error, response, body){
console.log(request);
console.log(body); }
With this code I am getting 403 Forbidden but with the same code on other APIs e.g search/tweets it works fine.
What am I missing here ?
And no, the user is not private.
You have got an error on the called URL. It should be:
...
url: 'https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=' + userid,
...

Accessing the Spotify API data (i.e. tokens) from redirect_uri via nodejs then redirect to angular app

Hi I'm creating a web application using node.JS and AngularJS. I'm fairly new to both technologies.
This is my app setup:
node.JS + mongoDB REST API - This will handle all server side requests as well as communicate to Spotify (http://localhost:3000)
AngularJS - For the app itself (http://localhost:8080)
Spotify has recently made it's Spotify Web API public. I'm trying to retrieve the access token (and refresh token) so I can make API calls to them. I was able to get the access_token & refresh_token, however, since I'm coming from http://localhost:8080/test to http://localhost:3000/spotifyapi/login to initialize the auth then to http://localhost:3000/spotifyapi/callback to receive the tokens.
If you could please help/guide me on how to retrieve the tokens/make api calls then pass it back to my AngularJS app, it would be greatly appreciated.
Below are my codes:
I'm using grunt to compile all JS into one file in my Angular app
NODE.JS API (http://localhost:3000/spotifyapi)
spotify.js
var SpotifyWebApi = require('spotify-web-api-node');
var request = require('request');
var querystring = require('querystring');
var client_id = config.spotify.client_id,
client_secret = config.spotify.client_secret,
redirect_uri = config.spotify.redirect_uri;
var spotifyApi = new SpotifyWebApi({
client_id: client_id,
redirect_uri: redirect_uri
});
exports.login = function(req, res) {
var scope = 'user-read-private playlist-read playlist-read-private',
state = 'mixr-test';
res.redirect('https://accounts.spotify.com/authorize?' +
querystring.stringify({
response_type: 'code',
client_id: client_id,
scope: scope,
redirect_uri: redirect_uri,
state: state
}));
};
exports.callback = function(req, res) {
var code = req.query.code;
var authOptions = {
url: 'https://accounts.spotify.com/api/token',
form: {
code: code,
redirect_uri: redirect_uri,
grant_type: 'authorization_code',
client_id: client_id,
client_secret: client_secret
},
json: true
};
request.post(authOptions, function(error, response, body) {
if (!error && response.statusCode == 200) {
var access_token = body.access_token,
refresh_token = body.refresh_token;
var options = {
url: 'https://api.spotify.com/v1/me',
headers: {
'Authorization': 'Bearer ' + access_token
},
json: true
};
// res.send(options);
res.redirect('http://localhost:8080/#/test#' +
querystring.stringify({
access_token: access_token,
refresh_token: refresh_token
}));
}
res.send({
access_token: access_token,
refresh_token: refresh_token
});
});
};
exports.refreshToken = function(req, res) {
var refresh_token = req.query.refresh_token;
var authOptions = {
url: 'https:/accounts.spotify.com/api/token',
headers: {
'Authorization': 'Basic ' + (new Buffer(client_id + ':' +
client_secret).toString('base64'))
},
form: {
grant_type: 'refresh_token',
refresh_token: refresh_token
},
json: true
};
request.post(authOptions, function(error, response, body) {
if (!error && response.statusCode === 200) {
var access_token = body.access_token;
res.send({
'access_token': access_token
});
}
});
};
routeMap.js
module.exports = [
['/spotifyapi', 'spotify#index', 'get'],
['/spotifyapi/login', 'spotify#login', 'get'],
['/spotifyapi/callback', 'spotify#callback', 'get'],
['/spotifyapi/refreshToken', 'spotify#refreshToken', 'get'],
];
AngularJS app (http://localhost:8080/test)
SpotifyService.js
app.factory('SpotifyService', function($http) {
var apibaseUrl = "http://localhost:3000";
return {
login: function(config) {
return $http.get(apibaseUrl + '/spotifyapi/login');
},
callback: function(access_token, refresh_token) {
return $http.get(apibaseUrl + '/spotifyapi/callback', {access_token:access_token, refresh_token:refresh_token});
},
refresh: function(refresh_token) {
return $http.get(apibaseUrl + '/spotifyapi/refreshToken', {access_token: access_token, refresh_token: refresh_token});
},
getUsers: function(){
return http.get(apibaseUrl + '/users');
}
};
});
SpotifyCtrl.js
app.controller('TestCtrl', ['$scope', 'SpotifyService', function($scope, SpotifyService) {
$scope.access_token = '';
$scope.refresh_token = '';
var getLogin = function() {
SpotifyService.login().success(function(data){
SpotifyService.callback(access_token, refresh_token).success(function(data){
$scope.access_token = data.access_token;
$scope.refresh_token = data.refresh_token;
}).error(function(data){
console.log("error!" + data);
});
}).error(function(data){
console.log("error!" + data);
});
};
}
]);
spotify.jade
block content
div#container(ng-controller="SpotifyCtrl")
a(href="http://localhost:3000/spotifyapi/login" class="btn btn-large") Login via Spotify
p {{ access_token }}
p {{ refresh_token }}
I'm able to go to Spotify's login page -> authenticate. My redirect_uri is http://localhost:3000/spotifyapi/callback. When authentication is finished, I'm able to get my access_token and refresh_token but I'm still on my node.JS API server and I can't get any value from my Angular Service to pass to my view. How do I redirect from my redirect_uri back to my Angular app and be able to retrieve the access and refresh tokens via my Angular services?
I apologize for this lengthy post, I'm just in a road block right now on how to complete this module.
THANK YOU IN ADVANCE!

Categories