-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathapp.js
181 lines (153 loc) · 6.31 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// Require all of our node.js modules
var express = require('express'); // Express web server framework
var request = require('request'); // "Request" library
var cookieParser = require('cookie-parser');
var querystring = require('querystring');
var url = require('url');
var stateKey = 'spotify_auth_state';
var app = express();
// Set the view engine to EJS
// EJS files end with .ejs (see 'views' folder)
app.set('view engine', 'ejs');
// We need this following line to allow the use of public files
// Put any external files (.css, .js) in the 'public' folder.
app.use(express.static(__dirname + '/public'))
.use(cookieParser());
// Our main visualization page
// Please see: routes/home.js
// These fields are information from the Spotify Developer site.
// They should be kept private at all times.
var client_id = '';
var client_secret = '';
var redirect_uri = ''; // Your redirect uri
// Generates a random 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;
};
// Login route
app.get('/login', function(req, res) {
// We need to clear our old tokens or else the tree may not load (tokens expired).
res.clearCookie('myToken');
res.clearCookie('myRefreshToken');
// When logging in, we generate a random state for the Spotify login
var state = generateRandomString(16);
res.cookie(stateKey, state);
// your application requests authorization
var scope = 'user-top-read user-read-private playlist-modify-public playlist-modify-private';
res.redirect('https://accounts.spotify.com/authorize?' +
querystring.stringify({
response_type: 'code',
client_id: client_id,
scope: scope,
redirect_uri: redirect_uri,
state: state,
show_dialog : true
}));
});
// Logout
app.get('/logout', function(req, res) {
// When logging out and then in again, we generate a random state for the Spotify login
var state = generateRandomString(16);
res.cookie(stateKey, state);
// Logout and present a new login screen
res.redirect('https://accounts.spotify.com/en/logout?continue=https%3A%2F%2Faccounts.spotify.com%2Fen%2Fauthorize%3Fresponse_type%3Dcode%26client_id%3D8d9483d3d91b4031b96286a03fd88478%26scope%3Duser-read-recently-played%2520user-top-read%2520user-read-private%2520user-read-email%26redirect_uri%3Dhttp%3A%252F%252Flocalhost%3A8888%252Fhome%26state%3D' + state + '%26show_dialog%3Dtrue');
});
/*
Error, About, and Help pages
*/
app.get('/oops', function(req, res) {
res.render('oops');
});
app.get('/about', function(req, res) {
res.render('about');
});
app.get('/help', function(req, res) {
res.render('help');
});
// Callback route
// After a Spotify user logs in, this route is called.
app.get('/home', function(req, res) {
if (req.cookies['myToken'] != null) {
res.render('home', { access_token: '' });
} else {
var state = req.query.state || null;
var code = req.query.code || null;
// Here, we are basically doing an extra check to make sure this
// user actually logged in and didn't just guess our callback URI.
// More information: https://developer.spotify.com/web-api/authorization-guide/
var storedState = req.cookies ? req.cookies[stateKey] : null;
if (state === null || state !== storedState) {
res.redirect('/');
} else {
// Clear the state cookie.
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
};
// Perform a POST request to the Spotify API
// This will grab our new access token.
request.post(authOptions, function(error, response, body) {
if (!error && response.statusCode === 200) {
var access_token = body.access_token,
refresh_token = body.refresh_token;
// Save our token and refresh token as cookies
// This allows the users to refresh the visualization page
res.cookie('myToken', access_token);
res.cookie('myRefreshToken', refresh_token);
var options = {
url: 'https://api.spotify.com/v1/me',
headers: { 'Authorization': 'Bearer ' + access_token },
json: true
};
res.render('home', { access_token: access_token, refresh_token: refresh_token });
} else {
// If there is an error or the status is not 'OK' (200),
// Then we want to go back to the main login page.
res.redirect('/');
}
});
}
}
});
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
});
}
});
});
// If there is an unknown route, we will just re-route to our login page
app.all('*', function(req, res) {
res.redirect("http://localhost:8888/");
});
// Listen on the port 8888
// console.log('Listening on 8888');
app.listen(8888);