-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauthServer.js
More file actions
149 lines (123 loc) · 4.04 KB
/
authServer.js
File metadata and controls
149 lines (123 loc) · 4.04 KB
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
import express from "express";
import cors from "cors";
import open from "open";
import dotenv from "dotenv";
dotenv.config();
const app = express();
app.use(cors());
const client_id = process.env.SPOTIFY_CLIENT_ID;
const client_secret = process.env.SPOTIFY_CLIENT_SECRET;
const redirect_uri = "http://127.0.0.1:8888/callback";
app.get("/login", (req, res) => {
const scopes = "user-read-currently-playing user-read-playback-state";
const authUrl = new URL("https://accounts.spotify.com/authorize");
authUrl.search = new URLSearchParams({
client_id,
response_type: "code",
redirect_uri,
scope: scopes,
}).toString();
// This line actually sends you to Spotify’s login
res.redirect(authUrl.toString());
});
let access_token = null;
let refresh_token = null;
let token_expires_in = null;
app.get("/callback", async (req, res) => {
const code = req.query.code || null;
const response = await fetch("https://accounts.spotify.com/api/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization:
"Basic " +
Buffer.from(
process.env.SPOTIFY_CLIENT_ID + ":" + process.env.SPOTIFY_CLIENT_SECRET
).toString("base64"),
},
body: new URLSearchParams({
grant_type: "authorization_code",
code: code,
redirect_uri: "http://127.0.0.1:8888/callback",
}),
});
const data = await response.json();
console.log("Initial token:", data);
access_token = data.access_token;
refresh_token = data.refresh_token;
token_expires_in = data.expires_in;
// Schedule auto-refresh 1 minute before expiry
scheduleTokenRefresh(token_expires_in - 60);
res.send("Authenticated! You can close this tab.");
});
// --- REFRESH LOGIC ---
async function refreshAccessToken() {
console.log("Refreshing access token...");
const response = await fetch("https://accounts.spotify.com/api/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization:
"Basic " +
Buffer.from(
process.env.SPOTIFY_CLIENT_ID + ":" + process.env.SPOTIFY_CLIENT_SECRET
).toString("base64"),
},
body: new URLSearchParams({
grant_type: "refresh_token",
refresh_token: refresh_token,
}),
});
const data = await response.json();
console.log("Refreshed token:", data);
access_token = data.access_token;
token_expires_in = data.expires_in;
// reschedule refresh
scheduleTokenRefresh(token_expires_in - 60);
}
function scheduleTokenRefresh(seconds) {
setTimeout(refreshAccessToken, seconds * 1000);
console.log(`Scheduled next refresh in ${seconds / 60} minutes.`);
}
app.listen(8888, () => {
console.log("Auth server running on http://127.0.0.1:8888");
// open login page, NOT callback
open("http://127.0.0.1:8888/login");
});
app.get("/currently-playing", async (req, res) => {
const token = access_token;
const response = await fetch("https://api.spotify.com/v1/me/player/currently-playing", {
headers: { Authorization: `Bearer ${token}` },
});
if (response.status === 401) {
res.status(401).send("Token expired, need refresh");
return;
}
const data = await response.json();
res.json(data);
});
app.get("/refresh_token", async (req, res) => {
const refresh_token = globalThis.spotifyRefreshToken;
const response = await fetch("https://accounts.spotify.com/api/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization:
"Basic " +
Buffer.from(
process.env.SPOTIFY_CLIENT_ID + ":" + process.env.SPOTIFY_CLIENT_SECRET
).toString("base64"),
},
body: new URLSearchParams({
grant_type: "refresh_token",
refresh_token: refresh_token,
}),
});
const data = await response.json();
console.log("Refreshed:", data);
globalThis.spotifyAccessToken = data.access_token;
res.json(data);
});
app.get('/token', (req, res) => {
res.json({ access_token: access_token });
});