I'm trying to access the app.get('/playlists') but it keeps coming up a 404 status code error and the browser is displaying cannot GET /playlists
I'm unsure what I'm doing tthat is isn't accessible here's the code:
var express = require('express'); // Express web server framework
var stateKey = 'spotify_auth_state';
var app = express();
app.use(express.static(__dirname + '/public'))
.use(cors())
.use(cookieParser());
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);
});
// we can also pass the token to the browser to make requests from there
res.redirect('/#' +
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
});
}
});
app.get('/playlists', (req, res) => {
console.log(request.url);
response.send('Hello, /');
});
});
console.log('Listening on 8888');
app.listen(8888);
I can't figure out why the route won't work
Your /playlists endpoint is declared inside of the /refresh_token endpoint. Moving it outside of that should work.
Related
I'm using Express, Node, and EJS to fetch data from Spotify Web API. Without EJS, I'm able to send a request from browser and fetch data no problem. With EJS, code crashes with code: 'ERR_HTTP_HEADERS_SENT' once I send a request in the browser. I'm lost on how to stop express from sending headers that have already been set.
const express = require("express");
const request = require("request");
const app = express();
const secret = require("./secret");
const redirect_uri = "http://localhost:8888/callback";
const client_id = secret.client_id;
const client_secret = secret.client_secret;
const querystring = require("querystring");
let state = "abc123";
let scope =
"user-read-private user-read-email user-read-recently-played user-top-read";
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.set("view engine", "ejs");
// Request User Authorization
app.get("/login", function (req, res) {
return res.redirect(
"https://accounts.spotify.com/authorize?" +
querystring.stringify({
response_type: "code",
client_id: client_id,
scope: scope,
redirect_uri: redirect_uri,
state: state,
})
);
});
// Request Access Token
app.get("/callback", function (req, res) {
let code = req.query.code || null;
state = req.query.state || null;
if (state === null) {
return res.redirect(
"/#" +
querystring.stringify({
error: "state_mismatch",
})
);
} else {
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,
};
}
// User Recently Played Tracks
request.post(authOptions, function (error, response, body) {
if (!error && response.statusCode === 200) {
let access_token = body.access_token;
let refresh_token = body.refresh_token;
let options = {
url: "https://api.spotify.com/v1/me/player/recently-played",
headers: { Authorization: "Bearer " + access_token },
json: true,
};
// use the access token to access the Spotify Web API
request.get(options, function (error, response, body) {
let items = body.items;
// Track Names
for (let i = 0; i < items.length; i++) {
let trackName = items[i].track.name;
console.log(trackName);
}
// Artist Names
for (let i = 0; i < items.length; i++) {
let artistName = items[i].track.artists[0].name;
console.log(artistName);
}
});
// we can also pass the token to the browser to make requests from there
return res.redirect(
"/#" +
querystring.stringify({
access_token: access_token,
refresh_token: refresh_token,
})
);
} else {
return res.redirect(
"/#" +
querystring.stringify({
error: "invalid_token",
})
);
}
});
return res.render("index");
});
// Refresh Token
app.get("/refresh_token", function (req, res) {
let refresh_token = req.query.refresh_token;
let 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) {
let access_token = body.access_token;
return res.send({
access_token: access_token,
});
}
});
});
app.listen(8888, () => console.log("Server started on port 8888"));
I have an express server that gets a list of podcasts, from an endpoint.
This apart works fine, but there is a token that I use in requests to authorize entry to the endpoints.
the response when gaining an access token looks like:
{ access_token: '8c9d31761cbd32da25f1f1b988b527cde01c9d8a',
expires_in: 604800,
token_type: 'Bearer',
scope: 'podcast_read episode_read podcast_update episode_publish' }
I have a refresh token that I use when refreshing the token and works well.
The way I'm doing it at the moment is, I have a text file that holds the token, the app reads from this when making a request, I have set up a function, that is called every time the podcasts route is called router.get('/podcasts', checkIfTokenValid, (req, res, next) => { to check if the token is valid or expired if so, refresh the token and write the new token to the file.
The only thing about this is; the write to file function is executed after the podcasts route connects to the endpoint, so the old access token is used.
Logging to the console, the functions are executed before the podcasts route gets all the podcasts, except for the writeAccessTokenToFile() function.
Just wondering, is there a better way to do this?
var express = require('express');
var router = express.Router();
var app = express();
var path = require('path');
var fs = require('fs');
const request = require('request');
var refreshToken = '425153ed4ddb4aee5sjsjsfaeffc46ab9944aece0400f';
var clientId = 'myId';
var client_secret = 'secret';
var isAccessTokenValid;
var access_token_file = path.join(__dirname, 'access_token.txt');
function refreshAccessToken() {
console.log('refreshAccessToken')
var body = { 'grant_type': 'refresh_token', 'refresh_token': refreshToken }
var options = {
url: `https://api.podbean.com/v1/oauth/token`,
headers: { 'Authorization': 'Basic ' + new Buffer(clientId + ":" + client_secret).toString('base64') },
json: body
}
request.post(options, (err, response, body) => {
// console.log(body.expires_in*1000)
if (err) {
return response.status(500).json({
title: 'An error has occured',
error: err
})
}
console.log(body)
writeAccessTokenToFile(body.access_token);
})
}
function getAccessToken() {
return fs.readFileSync(access_token_file, 'utf8');
}
function writeAccessTokenToFile(token) {
console.log('writeAccessTokenToFile = '+ token)
var data = getAccessToken();
var result = data.replace(data, token);
fs.writeFileSync(access_token_file, result, 'utf8');
}
function checkIfTokenValid (req, res, next) {
console.log('checkIfTokenValid')
var options = {
url: `https://api.podbean.com/v1/oauth/debugToken?access_token=${getAccessToken()}`,
headers: { 'Authorization': 'Basic ' + new Buffer(clientId + ":" + client_secret).toString('base64') }
}
request(options, (err, response, body) => {
if (err) {
return res.status(500).json({
title: 'An error has occured',
error: err
})
}
// console.log(JSON.parse(body))
isAccessTokenValid = JSON.parse(body).is_valid;
if (isAccessTokenValid) {
refreshAccessToken();
}
next();
})
};
router.get('/podcasts', checkIfTokenValid, (req, res, next) => {
var options = {
url: `https://api.podbean.com/v1/podcasts?access_token=${getAccessToken()}`
}
request(options, (err, response, body) => {
if (err) {
return res.status(500).json({
title: 'An error has occured',
error: err
})
}
res.json(JSON.parse(body));
next();
})
});
module.exports = router;
I have a nodejs app that throws the error every time I try and start the app using the command "node index.js":
app.post('/login', async (req, res) => {
^
SyntaxError: Unexpected token (
I understand how generic this error is, but I need a bit of direction. This application specifically is for iframe-auth detailed in rocket.chats documentation for utilizing a 3rd party API to login instead rocket chat's native login system.
The entire code of the app is here:
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request-promise');
var session = require('express-session');
const cookieParser = require('cookie-parser');
var app = express();
const rocketChatServer = '*redacted*';
const rocketChatAdminUserId = '*redacted*';
const rocketChatAdminAuthToken = '*redacted*';
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//CORS in case you need
app.use((req, res, next) => {
res.set('Access-Control-Allow-Origin', '*redacted*');
res.set('Access-Control-Allow-Credentials', 'true');
next();
});
// define middleware
const middleware = [
cookieParser(),
session({
secret: 'super-secret-key',
key: 'super-secret-cookie',
resave: true,
saveUninitialized: true,
cookie: { maxAge: 1209600000 } // two weeks in miliseconds
})
]
app.use(middleware);
//var createOrLoginUser = require('./rocketchat');
app.get('/', (req, res) => {
if(req.session.rocketchatAuthToken){
res.send(`
<html>
<body>
<iframe width='100%;' height='100%' src="*redacted*"
frameborder="0"></iframe>
</body>
</html>`);
}else{
res.send(`
<form method="post" action="/login">
<input type="text" placeholder="username" name="username">
<input type="text" placeholder="firstName"
name="firstname">
<input type="text" placeholder="Email" name="email">
<input type="text" placeholder="Pass" name="password">
<input type="submit" value="Submit">
</form>
`);
}
})
app.post('/login', async (req, res) => {
// ....CODE TO LOGIN USER
var username = req.body.username;
var pass = req.body.password;
var email = req.body.email;
var name = req.body.firstname;
// Creating or login user into Rocket chat
try {
// Request of login for 3rd party API
var options = { method: 'GET',
url: '*redacted*',
qs:
{ hashKey: '*redacted*',
sitename: username,
password: pass },
headers:
{ 'Postman-Token': '*redacted*',
'Cache-Control': 'no-cache' } };
const third_party_response = await request(options);
var result_third_party = JSON.parse(third_party_response);
console.log(result_third_party);
console.log(result_third_party.email);
if(result_third_party.email != ''){
// Request of login for Rocket Chat
var options = { method: 'POST',
url: `${rocketChatServer}/api/v1/login`,
headers:
{ 'Postman-Token': '*redacted*',
'Cache-Control': 'no-cache',
'Content-Type': 'application/x-www-form-urlencoded' },
form: { username: username, password: pass } };
const response = await request(options);
var result = JSON.parse(response);
req.session.rocketchatAuthToken = result.data.authToken;
res.redirect('/');
}else{
res.send('You are not registered with 3rd party API!');
}
} catch (ex) { console.log('CATHCh');
if (ex.statusCode === 401) {
// User does not exist, creating user
var options = { method: 'POST',
url: '*redacted*',
headers:
{ 'Postman-Token': '*redacted*',
'Cache-Control': 'no-cache',
'Content-Type': 'application/x-www-form-urlencoded',
'X-User-Id': rocketChatAdminUserId,
'X-Auth-Token': rocketChatAdminAuthToken },
form:
{ name: name ,
email: email,
password: pass,
username: username } };
const response_register = await request(options);
var result_register = JSON.parse(response_register);
if(result_register.success){
// on success login users
var options = { method: 'POST',
url: `${rocketChatServer}/api/v1/login`,
headers:
{ 'Postman-Token': '*redacted*',
'Cache-Control': 'no-cache',
'Content-Type': 'application/x-www-form-urlencoded' },
form: { username: username, password: pass } };
const response = await request(options);
var result = JSON.parse(response);
req.session.rocketchatAuthToken = result.data.authToken;
res.redirect('/');
}else{
console.log('Failed to create account');
}
// Perfom login
//return await loginUser(email, password);
} else {
throw ex;
}
}
})
// This method will be called by Rocket.chat to fetch the login token
app.get('/api/v1/rocket_chat_auth_get', (req, res) => {
if (req.session.rocketchatAuthToken) {
res.send({ loginToken: req.session.rocketchatAuthToken })
return;
} else {
res.status(401).json({ message: 'User not logged in'});
return;
}
})
// This method will be called by Rocket.chat to fetch the login token
// and is used as a fallback
app.get('/api/v1/rocket_chat_iframe', (req, res) => {
const rocketChatServer = '*redacted*';
if (req.session.rocketchatAuthToken) {
return res.send(`<script>
window.parent.postMessage({
event: 'login-with-token',
loginToken: '${ req.session.rocketchatAuthToken }'
}, '${ rocketChatServer }');
</script>
`)
return;
} else {
return res.redirect('/login');
}
})
app.listen(3030, function () {
console.log('Example app listening on port 3030!');
});
You must be using the wrong version of node. The async keyword requires node 8 or later.
I'm trying to use the spotify api to get data for my top artists and songs. I followed the authorization code examples here https://github.com/spotify/web-api-auth-examples. The authorization works and I can log in and see my basic info and now I'm trying to get my top artists however I get a 400 error: "Only valid bearer authentication supported".
Here's my code for this
app.get('/get_top_artists', function(req, res) {
var authString = 'Basic' + new Buffer(client_id + ':' + client_secret).toString('base64')
var authOptions = {
url: 'https://api.spotify.com/v1/me/top/artists',
headers: {
'Authorization': authString
}, function(res) {
console.log(res)
}
};
request.post(authOptions, function(error, response, body) {
if (!error && response.statusCode === 200) {
var get_top_artists = body.get_top_artists;
res.send({
'get_top_artists': get_top_artists
});
}
});
})
EDIT
app.get('/get_top_artists', function(req, res) {
console.log('top artists');
var authOptions = {
url: 'https://accounts.spotify.com/api/token',
form: {
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) {
console.log('request')
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/top/artists',
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('request 2')
console.log(body);
});
}
});
})
As you can see in the example, you need to first make the call with the basic header, and then take the response you get and THEN make the call to the API. Looks like you're trying to make the call to the API with the Basic credentials, which won't work.
https://github.com/spotify/web-api-auth-examples/blob/master/authorization_code/app.js#L73-L102
I was able to upload files to dropbox using request.js module. I was trying to upload file using pure Node.js https.request() and request.write(). As dropbox needs https connection, I am using https.request(). But I am receiving error while using them(second code):
When secureProtocol is SSLv2_method:
Problem with request: 3074844416:error:140650B5:SSL routines:CLIENT_HELLO:no ciphers available:../deps/openssl/openssl/ssl/s2_clnt.c:562:
After I change secureProtocol to SSLv3_method I receive error:
Problem with request: write EPROTO 3074537216:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:../deps/openssl/openssl/ssl/s3_pkt.c:348:
I was not able to install kerberos. Could this be the problem ?
Here are my code:
Using request.js module:
At last few lines I am piping the readable stream to request.put().
var crypto = require('crypto'),
express = require('express'),
request = require('request'),
url = require('url'),
cookieParser = require('cookie-parser'),
fs = require('fs');
app = express();
app.use(cookieParser());
var APP_KEY = 'opmdwo6kpnyswfp';
var APP_SECRET = 'an6vl11lc9rp51e';
function generateCSRFToken() {
return crypto.randomBytes(18).toString('base64')
.replace(/\//g,'-').replace(/\+/g,'_');
}
function generateRedirectURI(req) {
return url.format({
protocol: req.protocol,
host: req.headers.host,
pathname: app.path() + '/callback'
});
}
function getFileSize(fileName) {
var stats = fs.statSync(fileName);
var fileSizeInBytes = stats["size"];
var fileSizeInMegaBytes = fileSizeInBytes / 1000000.0;
return fileSizeInBytes;
}
app.get('/', function(req, res, next) {
var csrfToken = generateCSRFToken();
res.cookie('csrf',csrfToken);
res.redirect(url.format({
protocol: 'https',
hostname: 'www.dropbox.com',
pathname: '1/oauth2/authorize',
query: {
client_id: APP_KEY,
response_type: 'code',
state: csrfToken,
redirect_uri: generateRedirectURI(req)
}
}));
});
app.get('/callback', function(req, res) {
if(req.query.error) {
return res.send('ERROR ' + req.query.error + ': ' +
req.query.error_description);
}
if(req.query.state !== req.cookies.csrf) {
return res.status(401).send('CSRF token mismatch, possible' +
'cross-site request forgery attempt.'
);
}
request.post('https://api.dropbox.com/1/oauth2/token', {
form: {
code: req.query.code,
grant_type: 'authorization_code',
redirect_uri: generateRedirectURI(req)
},
auth: {
user: APP_KEY,
pass: APP_SECRET
}
}, function(error, response, body) {
var data = JSON.parse(body);
if(data.error)
return res.send('ERROR: ' + data.error);
var token = data.access_token;
var fileName = "aai_success.pdf";
var path = encodeURI("https://content.dropboxapi.com/1/files_put/auto/" + fileName);
fs.createReadStream(fileName).pipe(request.put(path, {
headers: { Authorization: 'Bearer ' + token },
'Content-Length': getFileSize(fileName)
}, function(error, response, body) {
console.log(response);
}));
});
});
app.listen(3000, function() {
console.log('Application is running on port 3000');
});
Using Node.js https.request()
var crypto = require('crypto'),
https = require('https');
express = require('express'),
request = require('request'),
url = require('url'),
cookieParser = require('cookie-parser'),
fs = require('fs'),
app = express();
app.use(cookieParser());
var APP_KEY = 'opmdwo6kpnyswfp';
var APP_SECRET = 'an6vl11lc9rp51e';
function generateCSRFToken() {
return crypto.randomBytes(18).toString('base64')
.replace(/\//g,'-').replace(/\+/g,'_');
}
function generateRedirectURI(req) {
return url.format({
protocol: req.protocol,
host: req.headers.host,
pathname: app.path() + '/callback'
});
}
function getFileSize(fileName) {
var stats = fs.statSync(fileName);
var fileSizeInBytes = stats["size"];
var fileSizeInMegaBytes = fileSizeInBytes / 1000000.0;
return fileSizeInBytes;
}
app.get('/', function(req, res, next) {
var csrfToken = generateCSRFToken();
res.cookie('csrf',csrfToken);
res.redirect(url.format({
protocol: 'https',
hostname: 'www.dropbox.com',
pathname: '1/oauth2/authorize',
query: {
client_id: APP_KEY,
response_type: 'code',
state: csrfToken,
redirect_uri: generateRedirectURI(req)
}
}));
});
app.get('/callback', function(req, res) {
if(req.query.error) {
return res.send('ERROR ' + req.query.error + ': ' +
req.query.error_description);
}
if(req.query.state !== req.cookies.csrf) {
return res.status(401).send('CSRF token mismatch, possible' +
'cross-site request forgery attempt.'
);
}
request.post('https://api.dropbox.com/1/oauth2/token', {
form: {
code: req.query.code,
grant_type: 'authorization_code',
redirect_uri: generateRedirectURI(req)
},
auth: {
user: APP_KEY,
pass: APP_SECRET
}
}, function(error, response, body) {
var data = JSON.parse(body);
if(data.error)
return res.send('ERROR: ' + data.error);
var token = data.access_token;
console.log("Access token: " + token);
var fileName = "aai_success.pdf";
var options = {
hostname: 'content.dropboxapi.com',
port: 80,
path: '/1/files_put/auto/test.txt',
method: 'POST',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'multipart/form-data',
'Content-Length': 2,
'Transfer-Encoding': 'chunked'
},
strictSSL: false,
secureProtocol: 'SSLv3_method'
};
var rqst = https.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function(chunk) {
console.log('BODY: ' + chunk);
});
});
rqst.write('AB');
rqst.end();
rqst.on('error', function(e) {
console.log('Problem with request: ' + e.message);
});
/*
var bts = 0;
fs.createReadStream(fileName).on('data', function(chunk) {
console.log("Got %d bytes from disk: ", chunk.length);
bts += bts + chunk.length;
var bytesSent = rqst.write(chunk);
console.log('Bytes sent: ' + bytesSent);
});
if(bts == 240519)
rqst.end();
*/
});
});
app.listen(3000, function() {
console.log('Application is running on port 3000');
});
You need to obtain a server certificate. You can self sign one for development using openssl (assuming you're on Linux) or you can obtain temporarily free ones. You also have the option to buy one from a certificate authority. Once you obtain a certificate look at the node.js docs under HTTPS or look at TLS (recommended) you can use their examples verbatim to setup SSL. https://nodejs.org/api/https.html
https://nodejs.org/api/tls.html
Solved the problem.
Change the port number to 443 and
remove the Content-Type header in options variable.
Didn't need to use strictSSL and secureProtocol
Didn't need to use SSL certificate.