-
Notifications
You must be signed in to change notification settings - Fork 59
/
ClientCredentialsStrategy.ts
77 lines (63 loc) · 2.59 KB
/
ClientCredentialsStrategy.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
import type { SdkConfiguration, ICachingStrategy, AccessToken } from "../types.js";
import AccessTokenHelpers from "./AccessTokenHelpers.js";
import IAuthStrategy from "./IAuthStrategy.js";
export default class ClientCredentialsStrategy implements IAuthStrategy {
private static readonly cacheKey = "spotify-sdk:ClientCredentialsStrategy:token";
private configuration: SdkConfiguration | null = null;
private get cache(): ICachingStrategy { return this.configuration!.cachingStrategy; }
constructor(
private clientId: string,
private clientSecret: string,
private scopes: string[] = []
) {
}
public setConfiguration(configuration: SdkConfiguration): void {
this.configuration = configuration;
}
public async getOrCreateAccessToken(): Promise<AccessToken> {
const token = await this.cache.getOrCreate<AccessToken>(
ClientCredentialsStrategy.cacheKey,
async () => {
const token = await this.getTokenFromApi();
return AccessTokenHelpers.toCachable(token);
},
async (_) => {
const refreshed = await this.getTokenFromApi();
return AccessTokenHelpers.toCachable(refreshed);
}
);
return token;
}
public async getAccessToken(): Promise<AccessToken | null> {
const token = await this.cache.get<AccessToken>(ClientCredentialsStrategy.cacheKey);
return token;
}
public removeAccessToken(): void {
this.cache.remove(ClientCredentialsStrategy.cacheKey);
}
private async getTokenFromApi(): Promise<AccessToken> {
const options = {
grant_type: 'client_credentials',
scope: this.scopes.join(' ')
} as any;
const bodyAsString = Object.keys(options).map(key => key + '=' + options[key]).join('&');
const hasBuffer = typeof Buffer !== 'undefined';
const credentials = `${this.clientId}:${this.clientSecret}`;
const basicAuth = hasBuffer
? Buffer.from(credentials).toString('base64')
: btoa(credentials);
const result = await fetch("https://accounts.spotify.com/api/token", {
method: 'POST',
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": `Basic ${basicAuth}`
},
body: bodyAsString
});
if (result.status !== 200) {
throw new Error("Failed to get access token.");
}
const json = await result.json();
return json;
}
}