-
-
Notifications
You must be signed in to change notification settings - Fork 19
/
spotify-callback.ts
executable file
·97 lines (91 loc) · 2.7 KB
/
spotify-callback.ts
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
import { Handler } from '@netlify/functions';
import { auth, set } from '@upstash/redis';
import { createCipheriv, createHash, randomBytes } from 'crypto';
import { request } from 'undici';
function encrypt(text: string) {
const iv = randomBytes(16);
const key = Buffer.from(
createHash('sha256')
.update(String(process.env.ENCRYPTION_SECRET))
.digest('base64')
.substr(0, 32)
);
const cipher = createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return iv.toString('hex') + '|||' + encrypted.toString('hex');
}
const getTokenURL = (code: string, redirectUri: string) => {
return `https://accounts.spotify.com/api/token?grant_type=authorization_code&code=${code}&redirect_uri=${encodeURI(
redirectUri
)}`;
};
const errorResponse = (
message = 'Something went wrong...Oops!',
data: Record<string, any>
) => {
console.log('Error:', message, JSON.stringify(data));
return {
statusCode: 500,
body: JSON.stringify({
message,
...data,
}),
};
};
export const handler: Handler = async (event, context) => {
const {
SPOTIFY_REDIRECT_URI,
SPOTIFY_CLIENT_ID,
SPOTIFY_CLIENT_SECRET,
REDIS_URL,
REDIS_WRITE_TOKEN,
FRONT_END_REDIRECT_URI,
} = process.env;
const { code, state } = event.queryStringParameters;
const tokenFetchURL = getTokenURL(code, SPOTIFY_REDIRECT_URI);
const headers = {
authorization: `Basic ${Buffer.from(
`${SPOTIFY_CLIENT_ID}:${SPOTIFY_CLIENT_SECRET}`
).toString('base64')}`,
'content-type': 'application/x-www-form-urlencoded',
};
let bodyParsed: null | Record<string, any> = null;
try {
const { statusCode, body } = await request(tokenFetchURL, {
method: 'POST',
headers,
});
bodyParsed = await body.json();
if (statusCode !== 200) {
return errorResponse('Token request failed', {
body: bodyParsed,
statusCode,
});
}
} catch (error) {
return errorResponse('Failed Fetch', { error });
}
try {
auth(REDIS_URL, REDIS_WRITE_TOKEN);
const encrypted = encrypt(bodyParsed['refresh_token']);
const { error } = await set(state, encrypted);
if (error) {
return errorResponse('Token set failed', { error });
}
return {
statusCode: 200,
body: `<script>
if (window.opener) {
// send them to the opening window
window.opener.postMessage({message:'refresh'});
// close the popup
window.close();
}
</script>`,
};
} catch (error) {
console.error(error);
return errorResponse('Failed to set token', { error });
}
};