antarctic 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +24 -0
- package/README.md +155 -0
- package/dist/auth.d.ts +63 -0
- package/dist/auth.js +191 -0
- package/dist/client.d.ts +16 -0
- package/dist/client.js +105 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.js +69 -0
- package/dist/oauth2.d.ts +16 -0
- package/dist/oauth2.js +67 -0
- package/dist/oidc.d.ts +1 -0
- package/dist/oidc.js +11 -0
- package/dist/providers/42.d.ts +16 -0
- package/dist/providers/42.js +75 -0
- package/dist/providers/amazon-cognito.d.ts +21 -0
- package/dist/providers/amazon-cognito.js +76 -0
- package/dist/providers/anilist.d.ts +14 -0
- package/dist/providers/anilist.js +91 -0
- package/dist/providers/apple.d.ts +22 -0
- package/dist/providers/apple.js +106 -0
- package/dist/providers/atlassian.d.ts +17 -0
- package/dist/providers/atlassian.js +83 -0
- package/dist/providers/auth0.d.ts +21 -0
- package/dist/providers/auth0.js +80 -0
- package/dist/providers/authentik.d.ts +21 -0
- package/dist/providers/authentik.js +75 -0
- package/dist/providers/autodesk.d.ts +16 -0
- package/dist/providers/autodesk.js +60 -0
- package/dist/providers/battlenet.d.ts +16 -0
- package/dist/providers/battlenet.js +69 -0
- package/dist/providers/bitbucket.d.ts +15 -0
- package/dist/providers/bitbucket.js +79 -0
- package/dist/providers/box.d.ts +18 -0
- package/dist/providers/box.js +90 -0
- package/dist/providers/bungie.d.ts +17 -0
- package/dist/providers/bungie.js +72 -0
- package/dist/providers/coinbase.d.ts +18 -0
- package/dist/providers/coinbase.js +95 -0
- package/dist/providers/discord.d.ts +16 -0
- package/dist/providers/discord.js +68 -0
- package/dist/providers/donation-alerts.d.ts +17 -0
- package/dist/providers/donation-alerts.js +86 -0
- package/dist/providers/dribbble.d.ts +16 -0
- package/dist/providers/dribbble.js +73 -0
- package/dist/providers/dropbox.d.ts +16 -0
- package/dist/providers/dropbox.js +96 -0
- package/dist/providers/epicgames.d.ts +16 -0
- package/dist/providers/epicgames.js +60 -0
- package/dist/providers/etsy.d.ts +15 -0
- package/dist/providers/etsy.js +68 -0
- package/dist/providers/facebook.d.ts +16 -0
- package/dist/providers/facebook.js +80 -0
- package/dist/providers/figma.d.ts +15 -0
- package/dist/providers/figma.js +56 -0
- package/dist/providers/gitea.d.ts +19 -0
- package/dist/providers/gitea.js +62 -0
- package/dist/providers/github.d.ts +17 -0
- package/dist/providers/github.js +142 -0
- package/dist/providers/gitlab.d.ts +21 -0
- package/dist/providers/gitlab.js +64 -0
- package/dist/providers/google.d.ts +16 -0
- package/dist/providers/google.js +70 -0
- package/dist/providers/intuit.d.ts +16 -0
- package/dist/providers/intuit.js +66 -0
- package/dist/providers/kakao.d.ts +17 -0
- package/dist/providers/kakao.js +95 -0
- package/dist/providers/keycloak.d.ts +21 -0
- package/dist/providers/keycloak.js +74 -0
- package/dist/providers/kick.d.ts +18 -0
- package/dist/providers/kick.js +103 -0
- package/dist/providers/lichess.d.ts +14 -0
- package/dist/providers/lichess.js +63 -0
- package/dist/providers/line.d.ts +17 -0
- package/dist/providers/line.js +98 -0
- package/dist/providers/linear.d.ts +16 -0
- package/dist/providers/linear.js +112 -0
- package/dist/providers/linkedin.d.ts +17 -0
- package/dist/providers/linkedin.js +89 -0
- package/dist/providers/mastodon.d.ts +20 -0
- package/dist/providers/mastodon.js +67 -0
- package/dist/providers/mercadolibre.d.ts +17 -0
- package/dist/providers/mercadolibre.js +95 -0
- package/dist/providers/mercadopago.d.ts +17 -0
- package/dist/providers/mercadopago.js +95 -0
- package/dist/providers/microsoft-entra-id.d.ts +20 -0
- package/dist/providers/microsoft-entra-id.js +120 -0
- package/dist/providers/myanimelist.d.ts +15 -0
- package/dist/providers/myanimelist.js +56 -0
- package/dist/providers/naver.d.ts +17 -0
- package/dist/providers/naver.js +83 -0
- package/dist/providers/notion.d.ts +14 -0
- package/dist/providers/notion.js +65 -0
- package/dist/providers/okta.d.ts +22 -0
- package/dist/providers/okta.js +85 -0
- package/dist/providers/osu.d.ts +17 -0
- package/dist/providers/osu.js +82 -0
- package/dist/providers/patreon.d.ts +17 -0
- package/dist/providers/patreon.js +89 -0
- package/dist/providers/polar.d.ts +18 -0
- package/dist/providers/polar.js +100 -0
- package/dist/providers/reddit.d.ts +15 -0
- package/dist/providers/reddit.js +55 -0
- package/dist/providers/roblox.d.ts +16 -0
- package/dist/providers/roblox.js +67 -0
- package/dist/providers/salesforce.d.ts +21 -0
- package/dist/providers/salesforce.js +74 -0
- package/dist/providers/shikimori.d.ts +17 -0
- package/dist/providers/shikimori.js +81 -0
- package/dist/providers/slack.d.ts +14 -0
- package/dist/providers/slack.js +59 -0
- package/dist/providers/spotify.d.ts +15 -0
- package/dist/providers/spotify.js +67 -0
- package/dist/providers/startgg.d.ts +17 -0
- package/dist/providers/startgg.js +143 -0
- package/dist/providers/strava.d.ts +17 -0
- package/dist/providers/strava.js +85 -0
- package/dist/providers/synology.d.ts +9 -0
- package/dist/providers/synology.js +20 -0
- package/dist/providers/tiktok.d.ts +18 -0
- package/dist/providers/tiktok.js +109 -0
- package/dist/providers/tiltify.d.ts +17 -0
- package/dist/providers/tiltify.js +90 -0
- package/dist/providers/tumblr.d.ts +15 -0
- package/dist/providers/tumblr.js +63 -0
- package/dist/providers/twitch.d.ts +17 -0
- package/dist/providers/twitch.js +91 -0
- package/dist/providers/twitter.d.ts +16 -0
- package/dist/providers/twitter.js +67 -0
- package/dist/providers/vk.d.ts +16 -0
- package/dist/providers/vk.js +82 -0
- package/dist/providers/withings.d.ts +16 -0
- package/dist/providers/withings.js +120 -0
- package/dist/providers/workos.d.ts +16 -0
- package/dist/providers/workos.js +82 -0
- package/dist/providers/yahoo.d.ts +15 -0
- package/dist/providers/yahoo.js +65 -0
- package/dist/providers/yandex.d.ts +15 -0
- package/dist/providers/yandex.js +66 -0
- package/dist/providers/zoom.d.ts +16 -0
- package/dist/providers/zoom.js +66 -0
- package/dist/request.d.ts +26 -0
- package/dist/request.js +182 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +20 -0
- package/package.json +42 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createOAuth2Request, sendTokenRequest } from "../request.js";
|
|
2
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthState, OAuthProviderError, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
|
|
3
|
+
const authorizationEndpoint = "https://www.patreon.com/oauth2/authorize";
|
|
4
|
+
const tokenEndpoint = "https://www.patreon.com/api/oauth2/token";
|
|
5
|
+
const identityEndpoint = "https://www.patreon.com/api/oauth2/v2/identity";
|
|
6
|
+
const envPrefix = "PATREON";
|
|
7
|
+
const defaultScopes = ["identity", "identity[email]"];
|
|
8
|
+
export class Patreon {
|
|
9
|
+
clientId;
|
|
10
|
+
clientSecret;
|
|
11
|
+
redirectURI;
|
|
12
|
+
auth = null;
|
|
13
|
+
constructor(clientIdOrOptions, clientSecret, redirectURI) {
|
|
14
|
+
if (typeof clientIdOrOptions === "object") {
|
|
15
|
+
this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, {
|
|
16
|
+
clientSecret: true,
|
|
17
|
+
redirectURI: true
|
|
18
|
+
});
|
|
19
|
+
this.clientId = this.auth.clientId;
|
|
20
|
+
this.clientSecret = this.auth.clientSecret ?? "";
|
|
21
|
+
this.redirectURI = this.auth.redirectURI ?? "";
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
this.clientId = clientIdOrOptions;
|
|
25
|
+
this.clientSecret = clientSecret ?? "";
|
|
26
|
+
this.redirectURI = redirectURI ?? "";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
createAuthorizationURL(state, scopes) {
|
|
30
|
+
const url = new URL(authorizationEndpoint);
|
|
31
|
+
url.searchParams.set("response_type", "code");
|
|
32
|
+
url.searchParams.set("client_id", this.clientId);
|
|
33
|
+
url.searchParams.set("state", state);
|
|
34
|
+
if (scopes.length > 0) {
|
|
35
|
+
url.searchParams.set("scope", scopes.join(" "));
|
|
36
|
+
}
|
|
37
|
+
url.searchParams.set("redirect_uri", this.redirectURI);
|
|
38
|
+
return url;
|
|
39
|
+
}
|
|
40
|
+
async validateAuthorizationCode(code) {
|
|
41
|
+
const body = new URLSearchParams();
|
|
42
|
+
body.set("grant_type", "authorization_code");
|
|
43
|
+
body.set("code", code);
|
|
44
|
+
body.set("redirect_uri", this.redirectURI);
|
|
45
|
+
body.set("client_id", this.clientId);
|
|
46
|
+
body.set("client_secret", this.clientSecret);
|
|
47
|
+
const request = createOAuth2Request(tokenEndpoint, body);
|
|
48
|
+
const tokens = await sendTokenRequest(request);
|
|
49
|
+
return tokens;
|
|
50
|
+
}
|
|
51
|
+
async refreshAccessToken(refreshToken) {
|
|
52
|
+
const body = new URLSearchParams();
|
|
53
|
+
body.set("grant_type", "refresh_token");
|
|
54
|
+
body.set("refresh_token", refreshToken);
|
|
55
|
+
body.set("client_id", this.clientId);
|
|
56
|
+
body.set("client_secret", this.clientSecret);
|
|
57
|
+
const request = createOAuth2Request(tokenEndpoint, body);
|
|
58
|
+
const tokens = await sendTokenRequest(request);
|
|
59
|
+
return tokens;
|
|
60
|
+
}
|
|
61
|
+
async getAuthorizationURL(scopes) {
|
|
62
|
+
const auth = requireAuthConfig(this.auth);
|
|
63
|
+
const state = generateOAuthState();
|
|
64
|
+
const url = this.createAuthorizationURL(state, resolveScopes(scopes, auth, defaultScopes));
|
|
65
|
+
await saveOAuthState(auth.store, state, {});
|
|
66
|
+
return url;
|
|
67
|
+
}
|
|
68
|
+
async getUser(query) {
|
|
69
|
+
const auth = requireAuthConfig(this.auth);
|
|
70
|
+
const { code, state } = parseCallbackQuery(query);
|
|
71
|
+
await consumeOAuthState(auth.store, state);
|
|
72
|
+
const tokens = await this.validateAuthorizationCode(code);
|
|
73
|
+
const url = new URL(identityEndpoint);
|
|
74
|
+
url.searchParams.set("fields[user]", "email,full_name,image_url");
|
|
75
|
+
const response = await fetchUserProfile(url, tokens.accessToken());
|
|
76
|
+
const data = response.data;
|
|
77
|
+
if (typeof data !== "object" || data === null) {
|
|
78
|
+
throw new OAuthProviderError("Unexpected user profile response body");
|
|
79
|
+
}
|
|
80
|
+
const user = data;
|
|
81
|
+
const attributes = (typeof user.attributes === "object" && user.attributes !== null ? user.attributes : {});
|
|
82
|
+
return {
|
|
83
|
+
id: profileId(user.id),
|
|
84
|
+
name: profileString(attributes.full_name),
|
|
85
|
+
email: profileString(attributes.email),
|
|
86
|
+
image: profileString(attributes.image_url)
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface PolarOptions extends ProviderOptions {
|
|
4
|
+
}
|
|
5
|
+
export declare class Polar {
|
|
6
|
+
private clientId;
|
|
7
|
+
private clientSecret;
|
|
8
|
+
private redirectURI;
|
|
9
|
+
private auth;
|
|
10
|
+
constructor(options: PolarOptions);
|
|
11
|
+
constructor(clientId: string, clientSecret: string | null, redirectURI: string);
|
|
12
|
+
createAuthorizationURL(state: string, codeVerifier: string, scopes: string[]): URL;
|
|
13
|
+
validateAuthorizationCode(code: string, codeVerifier: string): Promise<OAuth2Tokens>;
|
|
14
|
+
refreshAccessToken(refreshToken: string): Promise<OAuth2Tokens>;
|
|
15
|
+
revokeToken(token: string): Promise<void>;
|
|
16
|
+
getAuthorizationURL(scopes?: string[]): Promise<URL>;
|
|
17
|
+
getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createS256CodeChallenge } from "../oauth2.js";
|
|
2
|
+
import { createOAuth2Request, sendTokenRequest, sendTokenRevocationRequest } from "../request.js";
|
|
3
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthCodeVerifier, generateOAuthState, InvalidOAuthCallbackError, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
|
|
4
|
+
const authorizationEndpoint = "https://polar.sh/oauth2/authorize";
|
|
5
|
+
const tokenEndpoint = "https://api.polar.sh/v1/oauth2/token";
|
|
6
|
+
const tokenRevocationEndpoint = "https://api.polar.sh/v1/oauth2/revoke";
|
|
7
|
+
const userinfoEndpoint = "https://api.polar.sh/v1/oauth2/userinfo";
|
|
8
|
+
const envPrefix = "POLAR";
|
|
9
|
+
const defaultScopes = ["openid", "profile", "email"];
|
|
10
|
+
// Polar.sh supports HTTP Basic Auth but `client_secret` is set as the default authentication method.
|
|
11
|
+
export class Polar {
|
|
12
|
+
clientId;
|
|
13
|
+
clientSecret;
|
|
14
|
+
redirectURI;
|
|
15
|
+
auth = null;
|
|
16
|
+
constructor(clientIdOrOptions, clientSecret, redirectURI) {
|
|
17
|
+
if (typeof clientIdOrOptions === "object") {
|
|
18
|
+
this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, { redirectURI: true });
|
|
19
|
+
this.clientId = this.auth.clientId;
|
|
20
|
+
this.clientSecret = this.auth.clientSecret;
|
|
21
|
+
this.redirectURI = this.auth.redirectURI ?? "";
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
this.clientId = clientIdOrOptions;
|
|
25
|
+
this.clientSecret = clientSecret ?? null;
|
|
26
|
+
this.redirectURI = redirectURI ?? "";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
createAuthorizationURL(state, codeVerifier, scopes) {
|
|
30
|
+
const url = new URL(authorizationEndpoint);
|
|
31
|
+
url.searchParams.set("client_id", this.clientId);
|
|
32
|
+
url.searchParams.set("response_type", "code");
|
|
33
|
+
url.searchParams.set("redirect_uri", this.redirectURI);
|
|
34
|
+
url.searchParams.set("state", state);
|
|
35
|
+
if (scopes.length > 0) {
|
|
36
|
+
url.searchParams.set("scope", scopes.join(" "));
|
|
37
|
+
}
|
|
38
|
+
const codeChallenge = createS256CodeChallenge(codeVerifier);
|
|
39
|
+
url.searchParams.set("code_challenge", codeChallenge);
|
|
40
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
41
|
+
return url;
|
|
42
|
+
}
|
|
43
|
+
async validateAuthorizationCode(code, codeVerifier) {
|
|
44
|
+
const body = new URLSearchParams();
|
|
45
|
+
body.set("code", code);
|
|
46
|
+
body.set("client_id", this.clientId);
|
|
47
|
+
if (this.clientSecret !== null) {
|
|
48
|
+
body.set("client_secret", this.clientSecret);
|
|
49
|
+
}
|
|
50
|
+
body.set("redirect_uri", this.redirectURI);
|
|
51
|
+
body.set("grant_type", "authorization_code");
|
|
52
|
+
body.set("code_verifier", codeVerifier);
|
|
53
|
+
const request = createOAuth2Request(tokenEndpoint, body);
|
|
54
|
+
const tokens = await sendTokenRequest(request);
|
|
55
|
+
return tokens;
|
|
56
|
+
}
|
|
57
|
+
async refreshAccessToken(refreshToken) {
|
|
58
|
+
const body = new URLSearchParams();
|
|
59
|
+
body.set("refresh_token", refreshToken);
|
|
60
|
+
body.set("client_id", this.clientId);
|
|
61
|
+
if (this.clientSecret !== null) {
|
|
62
|
+
body.set("client_secret", this.clientSecret);
|
|
63
|
+
}
|
|
64
|
+
body.set("grant_type", "refresh_token");
|
|
65
|
+
const request = createOAuth2Request(tokenEndpoint, body);
|
|
66
|
+
const tokens = await sendTokenRequest(request);
|
|
67
|
+
return tokens;
|
|
68
|
+
}
|
|
69
|
+
async revokeToken(token) {
|
|
70
|
+
const body = new URLSearchParams();
|
|
71
|
+
body.set("token", token);
|
|
72
|
+
const request = createOAuth2Request(tokenRevocationEndpoint, body);
|
|
73
|
+
await sendTokenRevocationRequest(request);
|
|
74
|
+
}
|
|
75
|
+
async getAuthorizationURL(scopes) {
|
|
76
|
+
const auth = requireAuthConfig(this.auth);
|
|
77
|
+
const state = generateOAuthState();
|
|
78
|
+
const codeVerifier = generateOAuthCodeVerifier();
|
|
79
|
+
const url = this.createAuthorizationURL(state, codeVerifier, resolveScopes(scopes, auth, defaultScopes));
|
|
80
|
+
await saveOAuthState(auth.store, state, { codeVerifier });
|
|
81
|
+
return url;
|
|
82
|
+
}
|
|
83
|
+
async getUser(query) {
|
|
84
|
+
const auth = requireAuthConfig(this.auth);
|
|
85
|
+
const { code, state } = parseCallbackQuery(query);
|
|
86
|
+
const stored = await consumeOAuthState(auth.store, state);
|
|
87
|
+
if (typeof stored.codeVerifier !== "string") {
|
|
88
|
+
throw new InvalidOAuthCallbackError("Missing PKCE code verifier for OAuth state");
|
|
89
|
+
}
|
|
90
|
+
const tokens = await this.validateAuthorizationCode(code, stored.codeVerifier);
|
|
91
|
+
const claims = await fetchUserProfile(userinfoEndpoint, tokens.accessToken());
|
|
92
|
+
return {
|
|
93
|
+
id: profileId(claims.sub),
|
|
94
|
+
name: profileString(claims.name),
|
|
95
|
+
email: profileString(claims.email),
|
|
96
|
+
// Polar's userinfo response has no avatar field.
|
|
97
|
+
image: null
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface RedditOptions extends ProviderOptions {
|
|
4
|
+
}
|
|
5
|
+
export declare class Reddit {
|
|
6
|
+
private client;
|
|
7
|
+
private auth;
|
|
8
|
+
constructor(options: RedditOptions);
|
|
9
|
+
constructor(clientId: string, clientSecret: string, redirectURI: string);
|
|
10
|
+
createAuthorizationURL(state: string, scopes: string[]): URL;
|
|
11
|
+
validateAuthorizationCode(code: string): Promise<OAuth2Tokens>;
|
|
12
|
+
refreshAccessToken(refreshToken: string): Promise<OAuth2Tokens>;
|
|
13
|
+
getAuthorizationURL(scopes?: string[]): Promise<URL>;
|
|
14
|
+
getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { OAuth2Client } from "../client.js";
|
|
2
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthState, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
|
|
3
|
+
const authorizationEndpoint = "https://www.reddit.com/api/v1/authorize";
|
|
4
|
+
const tokenEndpoint = "https://www.reddit.com/api/v1/access_token";
|
|
5
|
+
const userEndpoint = "https://oauth.reddit.com/api/v1/me";
|
|
6
|
+
const envPrefix = "REDDIT";
|
|
7
|
+
const defaultScopes = ["identity"];
|
|
8
|
+
export class Reddit {
|
|
9
|
+
client;
|
|
10
|
+
auth = null;
|
|
11
|
+
constructor(clientIdOrOptions, clientSecret, redirectURI) {
|
|
12
|
+
if (typeof clientIdOrOptions === "object") {
|
|
13
|
+
this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, {
|
|
14
|
+
clientSecret: true,
|
|
15
|
+
redirectURI: true
|
|
16
|
+
});
|
|
17
|
+
this.client = new OAuth2Client(this.auth.clientId, this.auth.clientSecret, this.auth.redirectURI);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
this.client = new OAuth2Client(clientIdOrOptions, clientSecret ?? null, redirectURI ?? null);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
createAuthorizationURL(state, scopes) {
|
|
24
|
+
const url = this.client.createAuthorizationURL(authorizationEndpoint, state, scopes);
|
|
25
|
+
return url;
|
|
26
|
+
}
|
|
27
|
+
async validateAuthorizationCode(code) {
|
|
28
|
+
const tokens = await this.client.validateAuthorizationCode(tokenEndpoint, code, null);
|
|
29
|
+
return tokens;
|
|
30
|
+
}
|
|
31
|
+
async refreshAccessToken(refreshToken) {
|
|
32
|
+
const tokens = await this.client.refreshAccessToken(tokenEndpoint, refreshToken, []);
|
|
33
|
+
return tokens;
|
|
34
|
+
}
|
|
35
|
+
async getAuthorizationURL(scopes) {
|
|
36
|
+
const auth = requireAuthConfig(this.auth);
|
|
37
|
+
const state = generateOAuthState();
|
|
38
|
+
const url = this.createAuthorizationURL(state, resolveScopes(scopes, auth, defaultScopes));
|
|
39
|
+
await saveOAuthState(auth.store, state, {});
|
|
40
|
+
return url;
|
|
41
|
+
}
|
|
42
|
+
async getUser(query) {
|
|
43
|
+
const auth = requireAuthConfig(this.auth);
|
|
44
|
+
const { code, state } = parseCallbackQuery(query);
|
|
45
|
+
await consumeOAuthState(auth.store, state);
|
|
46
|
+
const tokens = await this.validateAuthorizationCode(code);
|
|
47
|
+
const profile = await fetchUserProfile(userEndpoint, tokens.accessToken());
|
|
48
|
+
return {
|
|
49
|
+
id: profileId(profile.id),
|
|
50
|
+
name: profileString(profile.name),
|
|
51
|
+
email: null,
|
|
52
|
+
image: profileString(profile.icon_img)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface RobloxOptions extends ProviderOptions {
|
|
4
|
+
}
|
|
5
|
+
export declare class Roblox {
|
|
6
|
+
private client;
|
|
7
|
+
private auth;
|
|
8
|
+
constructor(options: RobloxOptions);
|
|
9
|
+
constructor(clientId: string, clientSecret: string | null, redirectURI: string);
|
|
10
|
+
createAuthorizationURL(state: string, codeVerifier: string, scopes: string[]): URL;
|
|
11
|
+
validateAuthorizationCode(code: string, codeVerifier: string): Promise<OAuth2Tokens>;
|
|
12
|
+
refreshAccessToken(refreshToken: string): Promise<OAuth2Tokens>;
|
|
13
|
+
revokeToken(token: string): Promise<void>;
|
|
14
|
+
getAuthorizationURL(scopes?: string[]): Promise<URL>;
|
|
15
|
+
getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { OAuth2Client, CodeChallengeMethod } from "../client.js";
|
|
2
|
+
import { decodeIdToken } from "../oidc.js";
|
|
3
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthCodeVerifier, generateOAuthState, InvalidOAuthCallbackError, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
|
|
4
|
+
const authorizationEndpoint = "https://apis.roblox.com/oauth/v1/authorize";
|
|
5
|
+
const tokenEndpoint = "https://apis.roblox.com/oauth/v1/token";
|
|
6
|
+
const tokenRevocationEndpoint = "https://apis.roblox.com/oauth/v1/token/revoke";
|
|
7
|
+
const userinfoEndpoint = "https://apis.roblox.com/oauth/v1/userinfo";
|
|
8
|
+
const envPrefix = "ROBLOX";
|
|
9
|
+
const defaultScopes = ["openid", "profile"];
|
|
10
|
+
export class Roblox {
|
|
11
|
+
client;
|
|
12
|
+
auth = null;
|
|
13
|
+
constructor(clientIdOrOptions, clientSecret, redirectURI) {
|
|
14
|
+
if (typeof clientIdOrOptions === "object") {
|
|
15
|
+
this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, { redirectURI: true });
|
|
16
|
+
this.client = new OAuth2Client(this.auth.clientId, this.auth.clientSecret, this.auth.redirectURI);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
this.client = new OAuth2Client(clientIdOrOptions, clientSecret ?? null, redirectURI ?? null);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
createAuthorizationURL(state, codeVerifier, scopes) {
|
|
23
|
+
const url = this.client.createAuthorizationURLWithPKCE(authorizationEndpoint, state, CodeChallengeMethod.S256, codeVerifier, scopes);
|
|
24
|
+
return url;
|
|
25
|
+
}
|
|
26
|
+
async validateAuthorizationCode(code, codeVerifier) {
|
|
27
|
+
const tokens = await this.client.validateAuthorizationCode(tokenEndpoint, code, codeVerifier);
|
|
28
|
+
return tokens;
|
|
29
|
+
}
|
|
30
|
+
async refreshAccessToken(refreshToken) {
|
|
31
|
+
const tokens = await this.client.refreshAccessToken(tokenEndpoint, refreshToken, []);
|
|
32
|
+
return tokens;
|
|
33
|
+
}
|
|
34
|
+
async revokeToken(token) {
|
|
35
|
+
await this.client.revokeToken(tokenRevocationEndpoint, token);
|
|
36
|
+
}
|
|
37
|
+
async getAuthorizationURL(scopes) {
|
|
38
|
+
const auth = requireAuthConfig(this.auth);
|
|
39
|
+
const state = generateOAuthState();
|
|
40
|
+
const codeVerifier = generateOAuthCodeVerifier();
|
|
41
|
+
const url = this.createAuthorizationURL(state, codeVerifier, resolveScopes(scopes, auth, defaultScopes));
|
|
42
|
+
await saveOAuthState(auth.store, state, { codeVerifier });
|
|
43
|
+
return url;
|
|
44
|
+
}
|
|
45
|
+
async getUser(query) {
|
|
46
|
+
const auth = requireAuthConfig(this.auth);
|
|
47
|
+
const { code, state } = parseCallbackQuery(query);
|
|
48
|
+
const stored = await consumeOAuthState(auth.store, state);
|
|
49
|
+
if (typeof stored.codeVerifier !== "string") {
|
|
50
|
+
throw new InvalidOAuthCallbackError("Missing PKCE code verifier for OAuth state");
|
|
51
|
+
}
|
|
52
|
+
const tokens = await this.validateAuthorizationCode(code, stored.codeVerifier);
|
|
53
|
+
let claims;
|
|
54
|
+
if ("id_token" in tokens.data) {
|
|
55
|
+
claims = decodeIdToken(tokens.idToken());
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
claims = await fetchUserProfile(userinfoEndpoint, tokens.accessToken());
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
id: profileId(claims.sub),
|
|
62
|
+
name: profileString(claims.name) ?? profileString(claims.preferred_username),
|
|
63
|
+
email: null,
|
|
64
|
+
image: profileString(claims.picture)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface SalesforceOptions extends ProviderOptions {
|
|
4
|
+
domain?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class Salesforce {
|
|
7
|
+
private authorizationEndpoint;
|
|
8
|
+
private tokenEndpoint;
|
|
9
|
+
private tokenRevocationEndpoint;
|
|
10
|
+
private userinfoEndpoint;
|
|
11
|
+
private client;
|
|
12
|
+
private auth;
|
|
13
|
+
constructor(options: SalesforceOptions);
|
|
14
|
+
constructor(domain: string, clientId: string, clientSecret: string | null, redirectURI: string);
|
|
15
|
+
createAuthorizationURL(state: string, codeVerifier: string, scopes: string[]): URL;
|
|
16
|
+
validateAuthorizationCode(code: string, codeVerifier: string): Promise<OAuth2Tokens>;
|
|
17
|
+
refreshAccessToken(refreshToken: string): Promise<OAuth2Tokens>;
|
|
18
|
+
revokeToken(token: string): Promise<void>;
|
|
19
|
+
getAuthorizationURL(scopes?: string[]): Promise<URL>;
|
|
20
|
+
getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { OAuth2Client, CodeChallengeMethod } from "../client.js";
|
|
2
|
+
import { decodeIdToken } from "../oidc.js";
|
|
3
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthCodeVerifier, generateOAuthState, InvalidOAuthCallbackError, parseCallbackQuery, profileId, profileString, requireAuthConfig, requireProviderOption, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
|
|
4
|
+
const envPrefix = "SALESFORCE";
|
|
5
|
+
const defaultScopes = ["openid", "profile", "email"];
|
|
6
|
+
export class Salesforce {
|
|
7
|
+
authorizationEndpoint;
|
|
8
|
+
tokenEndpoint;
|
|
9
|
+
tokenRevocationEndpoint;
|
|
10
|
+
userinfoEndpoint;
|
|
11
|
+
client;
|
|
12
|
+
auth = null;
|
|
13
|
+
constructor(domainOrOptions, clientId, clientSecret, redirectURI) {
|
|
14
|
+
let domain;
|
|
15
|
+
if (typeof domainOrOptions === "object") {
|
|
16
|
+
this.auth = resolveAuthConfig(envPrefix, domainOrOptions, { redirectURI: true });
|
|
17
|
+
domain = requireProviderOption(domainOrOptions.domain, envPrefix, "DOMAIN", "domain");
|
|
18
|
+
this.client = new OAuth2Client(this.auth.clientId, this.auth.clientSecret, this.auth.redirectURI);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
domain = domainOrOptions;
|
|
22
|
+
this.client = new OAuth2Client(clientId ?? "", clientSecret ?? null, redirectURI ?? null);
|
|
23
|
+
}
|
|
24
|
+
this.authorizationEndpoint = `https://${domain}/services/oauth2/authorize`;
|
|
25
|
+
this.tokenEndpoint = `https://${domain}/services/oauth2/token`;
|
|
26
|
+
this.tokenRevocationEndpoint = `https://${domain}/services/oauth2/revoke`;
|
|
27
|
+
this.userinfoEndpoint = `https://${domain}/services/oauth2/userinfo`;
|
|
28
|
+
}
|
|
29
|
+
createAuthorizationURL(state, codeVerifier, scopes) {
|
|
30
|
+
const url = this.client.createAuthorizationURLWithPKCE(this.authorizationEndpoint, state, CodeChallengeMethod.S256, codeVerifier, scopes);
|
|
31
|
+
return url;
|
|
32
|
+
}
|
|
33
|
+
async validateAuthorizationCode(code, codeVerifier) {
|
|
34
|
+
const tokens = await this.client.validateAuthorizationCode(this.tokenEndpoint, code, codeVerifier);
|
|
35
|
+
return tokens;
|
|
36
|
+
}
|
|
37
|
+
async refreshAccessToken(refreshToken) {
|
|
38
|
+
const tokens = await this.client.refreshAccessToken(this.tokenEndpoint, refreshToken, []);
|
|
39
|
+
return tokens;
|
|
40
|
+
}
|
|
41
|
+
async revokeToken(token) {
|
|
42
|
+
await this.client.revokeToken(this.tokenRevocationEndpoint, token);
|
|
43
|
+
}
|
|
44
|
+
async getAuthorizationURL(scopes) {
|
|
45
|
+
const auth = requireAuthConfig(this.auth);
|
|
46
|
+
const state = generateOAuthState();
|
|
47
|
+
const codeVerifier = generateOAuthCodeVerifier();
|
|
48
|
+
const url = this.createAuthorizationURL(state, codeVerifier, resolveScopes(scopes, auth, defaultScopes));
|
|
49
|
+
await saveOAuthState(auth.store, state, { codeVerifier });
|
|
50
|
+
return url;
|
|
51
|
+
}
|
|
52
|
+
async getUser(query) {
|
|
53
|
+
const auth = requireAuthConfig(this.auth);
|
|
54
|
+
const { code, state } = parseCallbackQuery(query);
|
|
55
|
+
const stored = await consumeOAuthState(auth.store, state);
|
|
56
|
+
if (typeof stored.codeVerifier !== "string") {
|
|
57
|
+
throw new InvalidOAuthCallbackError("Missing PKCE code verifier for OAuth state");
|
|
58
|
+
}
|
|
59
|
+
const tokens = await this.validateAuthorizationCode(code, stored.codeVerifier);
|
|
60
|
+
let claims;
|
|
61
|
+
if ("id_token" in tokens.data) {
|
|
62
|
+
claims = decodeIdToken(tokens.idToken());
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
claims = await fetchUserProfile(this.userinfoEndpoint, tokens.accessToken());
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
id: profileId(claims.sub),
|
|
69
|
+
name: profileString(claims.name) ?? profileString(claims.preferred_username),
|
|
70
|
+
email: profileString(claims.email),
|
|
71
|
+
image: profileString(claims.picture)
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface ShikimoriOptions extends ProviderOptions {
|
|
4
|
+
}
|
|
5
|
+
export declare class Shikimori {
|
|
6
|
+
private clientId;
|
|
7
|
+
private clientSecret;
|
|
8
|
+
private redirectURI;
|
|
9
|
+
private auth;
|
|
10
|
+
constructor(options: ShikimoriOptions);
|
|
11
|
+
constructor(clientId: string, clientSecret: string, redirectURI: string);
|
|
12
|
+
createAuthorizationURL(state: string): URL;
|
|
13
|
+
validateAuthorizationCode(code: string): Promise<OAuth2Tokens>;
|
|
14
|
+
refreshAccessToken(refreshToken: string): Promise<OAuth2Tokens>;
|
|
15
|
+
getAuthorizationURL(): Promise<URL>;
|
|
16
|
+
getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { createOAuth2Request, sendTokenRequest } from "../request.js";
|
|
2
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthState, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, saveOAuthState } from "../auth.js";
|
|
3
|
+
const authorizationEndpoint = "https://shikimori.one/oauth/authorize";
|
|
4
|
+
const tokenEndpoint = "https://shikimori.one/oauth/token";
|
|
5
|
+
const userEndpoint = "https://shikimori.one/api/users/whoami";
|
|
6
|
+
const envPrefix = "SHIKIMORI";
|
|
7
|
+
export class Shikimori {
|
|
8
|
+
clientId;
|
|
9
|
+
clientSecret;
|
|
10
|
+
redirectURI;
|
|
11
|
+
auth = null;
|
|
12
|
+
constructor(clientIdOrOptions, clientSecret, redirectURI) {
|
|
13
|
+
if (typeof clientIdOrOptions === "object") {
|
|
14
|
+
this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, {
|
|
15
|
+
clientSecret: true,
|
|
16
|
+
redirectURI: true
|
|
17
|
+
});
|
|
18
|
+
this.clientId = this.auth.clientId;
|
|
19
|
+
this.clientSecret = this.auth.clientSecret ?? "";
|
|
20
|
+
this.redirectURI = this.auth.redirectURI ?? "";
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
this.clientId = clientIdOrOptions;
|
|
24
|
+
this.clientSecret = clientSecret ?? "";
|
|
25
|
+
this.redirectURI = redirectURI ?? "";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
createAuthorizationURL(state) {
|
|
29
|
+
const url = new URL(authorizationEndpoint);
|
|
30
|
+
url.searchParams.set("response_type", "code");
|
|
31
|
+
url.searchParams.set("client_id", this.clientId);
|
|
32
|
+
url.searchParams.set("state", state);
|
|
33
|
+
url.searchParams.set("redirect_uri", this.redirectURI);
|
|
34
|
+
return url;
|
|
35
|
+
}
|
|
36
|
+
async validateAuthorizationCode(code) {
|
|
37
|
+
const body = new URLSearchParams();
|
|
38
|
+
body.set("grant_type", "authorization_code");
|
|
39
|
+
body.set("code", code);
|
|
40
|
+
body.set("redirect_uri", this.redirectURI);
|
|
41
|
+
body.set("client_id", this.clientId);
|
|
42
|
+
body.set("client_secret", this.clientSecret);
|
|
43
|
+
const request = createOAuth2Request(tokenEndpoint, body);
|
|
44
|
+
const tokens = await sendTokenRequest(request);
|
|
45
|
+
return tokens;
|
|
46
|
+
}
|
|
47
|
+
async refreshAccessToken(refreshToken) {
|
|
48
|
+
const body = new URLSearchParams();
|
|
49
|
+
body.set("grant_type", "refresh_token");
|
|
50
|
+
body.set("refresh_token", refreshToken);
|
|
51
|
+
body.set("client_id", this.clientId);
|
|
52
|
+
body.set("client_secret", this.clientSecret);
|
|
53
|
+
const request = createOAuth2Request(tokenEndpoint, body);
|
|
54
|
+
const tokens = await sendTokenRequest(request);
|
|
55
|
+
return tokens;
|
|
56
|
+
}
|
|
57
|
+
async getAuthorizationURL() {
|
|
58
|
+
const auth = requireAuthConfig(this.auth);
|
|
59
|
+
const state = generateOAuthState();
|
|
60
|
+
const url = this.createAuthorizationURL(state);
|
|
61
|
+
await saveOAuthState(auth.store, state, {});
|
|
62
|
+
return url;
|
|
63
|
+
}
|
|
64
|
+
async getUser(query) {
|
|
65
|
+
const auth = requireAuthConfig(this.auth);
|
|
66
|
+
const { code, state } = parseCallbackQuery(query);
|
|
67
|
+
await consumeOAuthState(auth.store, state);
|
|
68
|
+
const tokens = await this.validateAuthorizationCode(code);
|
|
69
|
+
const profile = await fetchUserProfile(userEndpoint, tokens.accessToken());
|
|
70
|
+
let image = null;
|
|
71
|
+
if (typeof profile.image === "object" && profile.image !== null) {
|
|
72
|
+
image = profileString(profile.image.x160);
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
id: profileId(profile.id),
|
|
76
|
+
name: profileString(profile.nickname),
|
|
77
|
+
email: null,
|
|
78
|
+
image: image ?? profileString(profile.avatar)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface SlackOptions extends ProviderOptions {
|
|
4
|
+
}
|
|
5
|
+
export declare class Slack {
|
|
6
|
+
private client;
|
|
7
|
+
private auth;
|
|
8
|
+
constructor(options: SlackOptions);
|
|
9
|
+
constructor(clientId: string, clientSecret: string, redirectURI: string | null);
|
|
10
|
+
createAuthorizationURL(state: string, scopes: string[]): URL;
|
|
11
|
+
validateAuthorizationCode(code: string): Promise<OAuth2Tokens>;
|
|
12
|
+
getAuthorizationURL(scopes?: string[]): Promise<URL>;
|
|
13
|
+
getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { OAuth2Client } from "../client.js";
|
|
2
|
+
import { decodeIdToken } from "../oidc.js";
|
|
3
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthState, OAuthProviderError, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
|
|
4
|
+
const authorizationEndpoint = "https://slack.com/openid/connect/authorize";
|
|
5
|
+
const tokenEndpoint = "https://slack.com/api/openid.connect.token";
|
|
6
|
+
const userinfoEndpoint = "https://slack.com/api/openid.connect.userInfo";
|
|
7
|
+
const envPrefix = "SLACK";
|
|
8
|
+
const defaultScopes = ["openid", "profile", "email"];
|
|
9
|
+
export class Slack {
|
|
10
|
+
client;
|
|
11
|
+
auth = null;
|
|
12
|
+
constructor(clientIdOrOptions, clientSecret, redirectURI) {
|
|
13
|
+
if (typeof clientIdOrOptions === "object") {
|
|
14
|
+
this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, { clientSecret: true });
|
|
15
|
+
this.client = new OAuth2Client(this.auth.clientId, this.auth.clientSecret, this.auth.redirectURI);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
this.client = new OAuth2Client(clientIdOrOptions, clientSecret ?? "", redirectURI ?? null);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
createAuthorizationURL(state, scopes) {
|
|
22
|
+
const url = this.client.createAuthorizationURL(authorizationEndpoint, state, scopes);
|
|
23
|
+
return url;
|
|
24
|
+
}
|
|
25
|
+
async validateAuthorizationCode(code) {
|
|
26
|
+
const tokens = await this.client.validateAuthorizationCode(tokenEndpoint, code, null);
|
|
27
|
+
return tokens;
|
|
28
|
+
}
|
|
29
|
+
async getAuthorizationURL(scopes) {
|
|
30
|
+
const auth = requireAuthConfig(this.auth);
|
|
31
|
+
const state = generateOAuthState();
|
|
32
|
+
const url = this.createAuthorizationURL(state, resolveScopes(scopes, auth, defaultScopes));
|
|
33
|
+
await saveOAuthState(auth.store, state, {});
|
|
34
|
+
return url;
|
|
35
|
+
}
|
|
36
|
+
async getUser(query) {
|
|
37
|
+
const auth = requireAuthConfig(this.auth);
|
|
38
|
+
const { code, state } = parseCallbackQuery(query);
|
|
39
|
+
await consumeOAuthState(auth.store, state);
|
|
40
|
+
const tokens = await this.validateAuthorizationCode(code);
|
|
41
|
+
let claims;
|
|
42
|
+
if ("id_token" in tokens.data) {
|
|
43
|
+
claims = decodeIdToken(tokens.idToken());
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
claims = await fetchUserProfile(userinfoEndpoint, tokens.accessToken());
|
|
47
|
+
// Slack answers with HTTP 200 even when the call failed.
|
|
48
|
+
if (claims.ok === false) {
|
|
49
|
+
throw new OAuthProviderError(`User profile request failed: ${profileString(claims.error) ?? "unknown error"}`, profileString(claims.error));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
id: profileId(claims.sub),
|
|
54
|
+
name: profileString(claims.name),
|
|
55
|
+
email: profileString(claims.email),
|
|
56
|
+
image: profileString(claims.picture)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface SpotifyOptions extends ProviderOptions {
|
|
4
|
+
}
|
|
5
|
+
export declare class Spotify {
|
|
6
|
+
private client;
|
|
7
|
+
private auth;
|
|
8
|
+
constructor(options: SpotifyOptions);
|
|
9
|
+
constructor(clientId: string, clientSecret: string | null, redirectURI: string);
|
|
10
|
+
createAuthorizationURL(state: string, codeVerifier: string | null, scopes: string[]): URL;
|
|
11
|
+
validateAuthorizationCode(code: string, codeVerifier: string | null): Promise<OAuth2Tokens>;
|
|
12
|
+
refreshAccessToken(refreshToken: string): Promise<OAuth2Tokens>;
|
|
13
|
+
getAuthorizationURL(scopes?: string[]): Promise<URL>;
|
|
14
|
+
getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
|
|
15
|
+
}
|