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,60 @@
|
|
|
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.epicgames.com/id/authorize";
|
|
4
|
+
const tokenEndpoint = "https://api.epicgames.dev/epic/oauth/v2/token";
|
|
5
|
+
const tokenRevocationEndpoint = "https://api.epicgames.dev/epic/oauth/v2/revoke";
|
|
6
|
+
const userinfoEndpoint = "https://api.epicgames.dev/epic/oauth/v2/userInfo";
|
|
7
|
+
const envPrefix = "EPIC_GAMES";
|
|
8
|
+
const defaultScopes = ["basic_profile"];
|
|
9
|
+
export class EpicGames {
|
|
10
|
+
client;
|
|
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.client = new OAuth2Client(this.auth.clientId, this.auth.clientSecret, this.auth.redirectURI);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.client = new OAuth2Client(clientIdOrOptions, clientSecret ?? null, redirectURI ?? null);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
createAuthorizationURL(state, scopes) {
|
|
25
|
+
const url = this.client.createAuthorizationURL(authorizationEndpoint, state, scopes);
|
|
26
|
+
return url;
|
|
27
|
+
}
|
|
28
|
+
async validateAuthorizationCode(code) {
|
|
29
|
+
const tokens = await this.client.validateAuthorizationCode(tokenEndpoint, code, null);
|
|
30
|
+
return tokens;
|
|
31
|
+
}
|
|
32
|
+
async refreshAccessToken(refreshToken) {
|
|
33
|
+
const tokens = await this.client.refreshAccessToken(tokenEndpoint, refreshToken, []);
|
|
34
|
+
return tokens;
|
|
35
|
+
}
|
|
36
|
+
async revokeToken(token) {
|
|
37
|
+
await this.client.revokeToken(tokenRevocationEndpoint, token);
|
|
38
|
+
}
|
|
39
|
+
async getAuthorizationURL(scopes) {
|
|
40
|
+
const auth = requireAuthConfig(this.auth);
|
|
41
|
+
const state = generateOAuthState();
|
|
42
|
+
const url = this.createAuthorizationURL(state, resolveScopes(scopes, auth, defaultScopes));
|
|
43
|
+
await saveOAuthState(auth.store, state, {});
|
|
44
|
+
return url;
|
|
45
|
+
}
|
|
46
|
+
async getUser(query) {
|
|
47
|
+
const auth = requireAuthConfig(this.auth);
|
|
48
|
+
const { code, state } = parseCallbackQuery(query);
|
|
49
|
+
await consumeOAuthState(auth.store, state);
|
|
50
|
+
const tokens = await this.validateAuthorizationCode(code);
|
|
51
|
+
const claims = await fetchUserProfile(userinfoEndpoint, tokens.accessToken());
|
|
52
|
+
return {
|
|
53
|
+
id: profileId(claims.sub),
|
|
54
|
+
name: profileString(claims.preferred_username),
|
|
55
|
+
// Epic Games does not expose user emails or avatars.
|
|
56
|
+
email: null,
|
|
57
|
+
image: null
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface EtsyOptions extends ProviderOptions {
|
|
4
|
+
}
|
|
5
|
+
export declare class Etsy {
|
|
6
|
+
private client;
|
|
7
|
+
private auth;
|
|
8
|
+
constructor(options: EtsyOptions);
|
|
9
|
+
constructor(clientId: string, 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
|
+
getAuthorizationURL(scopes?: string[]): Promise<URL>;
|
|
14
|
+
getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { CodeChallengeMethod, OAuth2Client } from "../client.js";
|
|
2
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthCodeVerifier, generateOAuthState, InvalidOAuthCallbackError, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
|
|
3
|
+
const authorizationEndpoint = "https://www.etsy.com/oauth/connect";
|
|
4
|
+
const tokenEndpoint = "https://api.etsy.com/v3/public/oauth/token";
|
|
5
|
+
const meEndpoint = "https://openapi.etsy.com/v3/application/users/me";
|
|
6
|
+
const userEndpoint = "https://openapi.etsy.com/v3/application/users";
|
|
7
|
+
const envPrefix = "ETSY";
|
|
8
|
+
const defaultScopes = ["email_r"];
|
|
9
|
+
export class Etsy {
|
|
10
|
+
client;
|
|
11
|
+
auth = null;
|
|
12
|
+
constructor(clientIdOrOptions, redirectURI) {
|
|
13
|
+
if (typeof clientIdOrOptions === "object") {
|
|
14
|
+
this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, { redirectURI: true });
|
|
15
|
+
this.client = new OAuth2Client(this.auth.clientId, null, this.auth.redirectURI);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
this.client = new OAuth2Client(clientIdOrOptions, null, redirectURI ?? null);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
createAuthorizationURL(state, codeVerifier, scopes) {
|
|
22
|
+
const url = this.client.createAuthorizationURLWithPKCE(authorizationEndpoint, state, CodeChallengeMethod.S256, codeVerifier, scopes);
|
|
23
|
+
return url;
|
|
24
|
+
}
|
|
25
|
+
async validateAuthorizationCode(code, codeVerifier) {
|
|
26
|
+
const tokens = await this.client.validateAuthorizationCode(tokenEndpoint, code, codeVerifier);
|
|
27
|
+
return tokens;
|
|
28
|
+
}
|
|
29
|
+
async refreshAccessToken(refreshToken) {
|
|
30
|
+
const tokens = await this.client.refreshAccessToken(tokenEndpoint, refreshToken, []);
|
|
31
|
+
return tokens;
|
|
32
|
+
}
|
|
33
|
+
async getAuthorizationURL(scopes) {
|
|
34
|
+
const auth = requireAuthConfig(this.auth);
|
|
35
|
+
const state = generateOAuthState();
|
|
36
|
+
const codeVerifier = generateOAuthCodeVerifier();
|
|
37
|
+
const url = this.createAuthorizationURL(state, codeVerifier, resolveScopes(scopes, auth, defaultScopes));
|
|
38
|
+
await saveOAuthState(auth.store, state, { codeVerifier });
|
|
39
|
+
return url;
|
|
40
|
+
}
|
|
41
|
+
async getUser(query) {
|
|
42
|
+
const auth = requireAuthConfig(this.auth);
|
|
43
|
+
const { code, state } = parseCallbackQuery(query);
|
|
44
|
+
const stored = await consumeOAuthState(auth.store, state);
|
|
45
|
+
if (typeof stored.codeVerifier !== "string") {
|
|
46
|
+
throw new InvalidOAuthCallbackError("Missing PKCE code verifier for OAuth state");
|
|
47
|
+
}
|
|
48
|
+
const tokens = await this.validateAuthorizationCode(code, stored.codeVerifier);
|
|
49
|
+
const accessToken = tokens.accessToken();
|
|
50
|
+
// Etsy requires the app keystring as an API key header on every request.
|
|
51
|
+
const headers = { "x-api-key": auth.clientId };
|
|
52
|
+
const me = await fetchUserProfile(meEndpoint, accessToken, headers);
|
|
53
|
+
const userId = profileId(me.user_id);
|
|
54
|
+
const profile = await fetchUserProfile(`${userEndpoint}/${userId}`, accessToken, headers);
|
|
55
|
+
const firstName = profileString(profile.first_name);
|
|
56
|
+
const lastName = profileString(profile.last_name);
|
|
57
|
+
let name = null;
|
|
58
|
+
if (firstName !== null || lastName !== null) {
|
|
59
|
+
name = [firstName, lastName].filter((part) => part !== null).join(" ");
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
id: userId,
|
|
63
|
+
name,
|
|
64
|
+
email: profileString(profile.primary_email),
|
|
65
|
+
image: profileString(profile.image_url_75x75)
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface FacebookOptions extends ProviderOptions {
|
|
4
|
+
}
|
|
5
|
+
export declare class Facebook {
|
|
6
|
+
private clientId;
|
|
7
|
+
private clientSecret;
|
|
8
|
+
private redirectURI;
|
|
9
|
+
private auth;
|
|
10
|
+
constructor(options: FacebookOptions);
|
|
11
|
+
constructor(clientId: string, clientSecret: string, redirectURI: string);
|
|
12
|
+
createAuthorizationURL(state: string, scopes: string[]): URL;
|
|
13
|
+
validateAuthorizationCode(code: string): Promise<OAuth2Tokens>;
|
|
14
|
+
getAuthorizationURL(scopes?: string[]): Promise<URL>;
|
|
15
|
+
getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createOAuth2Request, sendTokenRequest } from "../request.js";
|
|
2
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthState, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
|
|
3
|
+
const authorizationEndpoint = "https://www.facebook.com/v16.0/dialog/oauth";
|
|
4
|
+
const tokenEndpoint = "https://graph.facebook.com/v16.0/oauth/access_token";
|
|
5
|
+
const userEndpoint = "https://graph.facebook.com/v16.0/me";
|
|
6
|
+
const envPrefix = "FACEBOOK";
|
|
7
|
+
const defaultScopes = ["public_profile", "email"];
|
|
8
|
+
export class Facebook {
|
|
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 getAuthorizationURL(scopes) {
|
|
52
|
+
const auth = requireAuthConfig(this.auth);
|
|
53
|
+
const state = generateOAuthState();
|
|
54
|
+
const url = this.createAuthorizationURL(state, resolveScopes(scopes, auth, defaultScopes));
|
|
55
|
+
await saveOAuthState(auth.store, state, {});
|
|
56
|
+
return url;
|
|
57
|
+
}
|
|
58
|
+
async getUser(query) {
|
|
59
|
+
const auth = requireAuthConfig(this.auth);
|
|
60
|
+
const { code, state } = parseCallbackQuery(query);
|
|
61
|
+
await consumeOAuthState(auth.store, state);
|
|
62
|
+
const tokens = await this.validateAuthorizationCode(code);
|
|
63
|
+
const url = new URL(userEndpoint);
|
|
64
|
+
url.searchParams.set("fields", "id,name,email,picture.width(256)");
|
|
65
|
+
const profile = await fetchUserProfile(url, tokens.accessToken());
|
|
66
|
+
let image = null;
|
|
67
|
+
if (typeof profile.picture === "object" && profile.picture !== null) {
|
|
68
|
+
const data = profile.picture.data;
|
|
69
|
+
if (typeof data === "object" && data !== null) {
|
|
70
|
+
image = profileString(data.url);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
id: profileId(profile.id),
|
|
75
|
+
name: profileString(profile.name),
|
|
76
|
+
email: profileString(profile.email),
|
|
77
|
+
image
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface FigmaOptions extends ProviderOptions {
|
|
4
|
+
}
|
|
5
|
+
export declare class Figma {
|
|
6
|
+
private client;
|
|
7
|
+
private auth;
|
|
8
|
+
constructor(options: FigmaOptions);
|
|
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,56 @@
|
|
|
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.figma.com/oauth";
|
|
4
|
+
const tokenEndpoint = "https://api.figma.com/v1/oauth/token";
|
|
5
|
+
const refreshEndpoint = "https://api.figma.com/v1/oauth/refresh";
|
|
6
|
+
const userEndpoint = "https://api.figma.com/v1/me";
|
|
7
|
+
const envPrefix = "FIGMA";
|
|
8
|
+
const defaultScopes = ["current_user:read"];
|
|
9
|
+
export class Figma {
|
|
10
|
+
client;
|
|
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.client = new OAuth2Client(this.auth.clientId, this.auth.clientSecret, this.auth.redirectURI);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.client = new OAuth2Client(clientIdOrOptions, clientSecret ?? null, redirectURI ?? null);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
createAuthorizationURL(state, scopes) {
|
|
25
|
+
const url = this.client.createAuthorizationURL(authorizationEndpoint, state, scopes);
|
|
26
|
+
return url;
|
|
27
|
+
}
|
|
28
|
+
async validateAuthorizationCode(code) {
|
|
29
|
+
const tokens = await this.client.validateAuthorizationCode(tokenEndpoint, code, null);
|
|
30
|
+
return tokens;
|
|
31
|
+
}
|
|
32
|
+
async refreshAccessToken(refreshToken) {
|
|
33
|
+
const tokens = await this.client.refreshAccessToken(refreshEndpoint, refreshToken, []);
|
|
34
|
+
return tokens;
|
|
35
|
+
}
|
|
36
|
+
async getAuthorizationURL(scopes) {
|
|
37
|
+
const auth = requireAuthConfig(this.auth);
|
|
38
|
+
const state = generateOAuthState();
|
|
39
|
+
const url = this.createAuthorizationURL(state, resolveScopes(scopes, auth, defaultScopes));
|
|
40
|
+
await saveOAuthState(auth.store, state, {});
|
|
41
|
+
return url;
|
|
42
|
+
}
|
|
43
|
+
async getUser(query) {
|
|
44
|
+
const auth = requireAuthConfig(this.auth);
|
|
45
|
+
const { code, state } = parseCallbackQuery(query);
|
|
46
|
+
await consumeOAuthState(auth.store, state);
|
|
47
|
+
const tokens = await this.validateAuthorizationCode(code);
|
|
48
|
+
const profile = await fetchUserProfile(userEndpoint, tokens.accessToken());
|
|
49
|
+
return {
|
|
50
|
+
id: profileId(profile.id),
|
|
51
|
+
name: profileString(profile.handle),
|
|
52
|
+
email: profileString(profile.email),
|
|
53
|
+
image: profileString(profile.img_url)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface GiteaOptions extends ProviderOptions {
|
|
4
|
+
baseURL?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class Gitea {
|
|
7
|
+
private authorizationEndpoint;
|
|
8
|
+
private tokenEndpoint;
|
|
9
|
+
private baseURL;
|
|
10
|
+
private client;
|
|
11
|
+
private auth;
|
|
12
|
+
constructor(options: GiteaOptions);
|
|
13
|
+
constructor(baseURL: string, clientId: string, clientSecret: string | null, redirectURI: string);
|
|
14
|
+
createAuthorizationURL(state: string, codeVerifier: string, scopes: string[]): URL;
|
|
15
|
+
validateAuthorizationCode(code: string, codeVerifier: string): Promise<OAuth2Tokens>;
|
|
16
|
+
refreshAccessToken(refreshToken: string): Promise<OAuth2Tokens>;
|
|
17
|
+
getAuthorizationURL(scopes?: string[]): Promise<URL>;
|
|
18
|
+
getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { CodeChallengeMethod, OAuth2Client } from "../client.js";
|
|
2
|
+
import { joinURIAndPath } from "../request.js";
|
|
3
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthCodeVerifier, generateOAuthState, InvalidOAuthCallbackError, parseCallbackQuery, profileId, profileString, requireAuthConfig, requireProviderOption, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
|
|
4
|
+
const envPrefix = "GITEA";
|
|
5
|
+
const defaultScopes = ["read:user"];
|
|
6
|
+
export class Gitea {
|
|
7
|
+
authorizationEndpoint;
|
|
8
|
+
tokenEndpoint;
|
|
9
|
+
baseURL;
|
|
10
|
+
client;
|
|
11
|
+
auth = null;
|
|
12
|
+
constructor(baseURLOrOptions, clientId, clientSecret, redirectURI) {
|
|
13
|
+
if (typeof baseURLOrOptions === "object") {
|
|
14
|
+
this.auth = resolveAuthConfig(envPrefix, baseURLOrOptions, { redirectURI: true });
|
|
15
|
+
this.baseURL = requireProviderOption(baseURLOrOptions.baseURL, envPrefix, "BASE_URL", "baseURL");
|
|
16
|
+
this.client = new OAuth2Client(this.auth.clientId, this.auth.clientSecret, this.auth.redirectURI);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
this.baseURL = baseURLOrOptions;
|
|
20
|
+
this.client = new OAuth2Client(clientId ?? "", clientSecret ?? null, redirectURI ?? null);
|
|
21
|
+
}
|
|
22
|
+
this.authorizationEndpoint = joinURIAndPath(this.baseURL, "/login/oauth/authorize");
|
|
23
|
+
this.tokenEndpoint = joinURIAndPath(this.baseURL, "/login/oauth/access_token");
|
|
24
|
+
}
|
|
25
|
+
createAuthorizationURL(state, codeVerifier, scopes) {
|
|
26
|
+
const url = this.client.createAuthorizationURLWithPKCE(this.authorizationEndpoint, state, CodeChallengeMethod.S256, codeVerifier, scopes);
|
|
27
|
+
return url;
|
|
28
|
+
}
|
|
29
|
+
async validateAuthorizationCode(code, codeVerifier) {
|
|
30
|
+
const tokens = await this.client.validateAuthorizationCode(this.tokenEndpoint, code, codeVerifier);
|
|
31
|
+
return tokens;
|
|
32
|
+
}
|
|
33
|
+
async refreshAccessToken(refreshToken) {
|
|
34
|
+
const tokens = await this.client.refreshAccessToken(this.tokenEndpoint, refreshToken, []);
|
|
35
|
+
return tokens;
|
|
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
|
+
const userEndpoint = joinURIAndPath(this.baseURL, "/api/v1/user");
|
|
54
|
+
const profile = await fetchUserProfile(userEndpoint, tokens.accessToken());
|
|
55
|
+
return {
|
|
56
|
+
id: profileId(profile.id),
|
|
57
|
+
name: profileString(profile.full_name) ?? profileString(profile.login),
|
|
58
|
+
email: profileString(profile.email),
|
|
59
|
+
image: profileString(profile.avatar_url)
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface GitHubOptions extends ProviderOptions {
|
|
4
|
+
}
|
|
5
|
+
export declare class GitHub {
|
|
6
|
+
private clientId;
|
|
7
|
+
private clientSecret;
|
|
8
|
+
private redirectURI;
|
|
9
|
+
private auth;
|
|
10
|
+
constructor(options: GitHubOptions);
|
|
11
|
+
constructor(clientId: string, clientSecret: string, redirectURI: string | null);
|
|
12
|
+
createAuthorizationURL(state: string, scopes: string[]): URL;
|
|
13
|
+
validateAuthorizationCode(code: string): Promise<OAuth2Tokens>;
|
|
14
|
+
refreshAccessToken(refreshToken: string): Promise<OAuth2Tokens>;
|
|
15
|
+
getAuthorizationURL(scopes?: string[]): Promise<URL>;
|
|
16
|
+
getUser(query: OAuthCallbackQuery): Promise<OAuthUser>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { ArcticFetchError, createOAuth2Request, createOAuth2RequestError, encodeBasicCredentials, UnexpectedErrorResponseBodyError, UnexpectedResponseError } from "../request.js";
|
|
2
|
+
import { OAuth2Tokens } from "../oauth2.js";
|
|
3
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthState, parseCallbackQuery, profileId, profileString, requireAuthConfig, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
|
|
4
|
+
const authorizationEndpoint = "https://github.com/login/oauth/authorize";
|
|
5
|
+
const tokenEndpoint = "https://github.com/login/oauth/access_token";
|
|
6
|
+
const userEndpoint = "https://api.github.com/user";
|
|
7
|
+
const userEmailsEndpoint = "https://api.github.com/user/emails";
|
|
8
|
+
const envPrefix = "GITHUB";
|
|
9
|
+
const defaultScopes = ["read:user", "user:email"];
|
|
10
|
+
export class GitHub {
|
|
11
|
+
clientId;
|
|
12
|
+
clientSecret;
|
|
13
|
+
redirectURI;
|
|
14
|
+
auth = null;
|
|
15
|
+
constructor(clientIdOrOptions, clientSecret, redirectURI) {
|
|
16
|
+
if (typeof clientIdOrOptions === "object") {
|
|
17
|
+
this.auth = resolveAuthConfig(envPrefix, clientIdOrOptions, { clientSecret: true });
|
|
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 ?? null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
createAuthorizationURL(state, scopes) {
|
|
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
|
+
if (scopes.length > 0) {
|
|
34
|
+
url.searchParams.set("scope", scopes.join(" "));
|
|
35
|
+
}
|
|
36
|
+
if (this.redirectURI !== null) {
|
|
37
|
+
url.searchParams.set("redirect_uri", this.redirectURI);
|
|
38
|
+
}
|
|
39
|
+
return url;
|
|
40
|
+
}
|
|
41
|
+
async validateAuthorizationCode(code) {
|
|
42
|
+
const body = new URLSearchParams();
|
|
43
|
+
body.set("grant_type", "authorization_code");
|
|
44
|
+
body.set("code", code);
|
|
45
|
+
if (this.redirectURI !== null) {
|
|
46
|
+
body.set("redirect_uri", this.redirectURI);
|
|
47
|
+
}
|
|
48
|
+
const request = createOAuth2Request(tokenEndpoint, body);
|
|
49
|
+
const encodedCredentials = encodeBasicCredentials(this.clientId, this.clientSecret);
|
|
50
|
+
request.headers.set("Authorization", `Basic ${encodedCredentials}`);
|
|
51
|
+
const tokens = await sendTokenRequest(request);
|
|
52
|
+
return tokens;
|
|
53
|
+
}
|
|
54
|
+
async refreshAccessToken(refreshToken) {
|
|
55
|
+
const body = new URLSearchParams();
|
|
56
|
+
body.set("grant_type", "refresh_token");
|
|
57
|
+
body.set("refresh_token", refreshToken);
|
|
58
|
+
const request = createOAuth2Request(tokenEndpoint, body);
|
|
59
|
+
const encodedCredentials = encodeBasicCredentials(this.clientId, this.clientSecret);
|
|
60
|
+
request.headers.set("Authorization", `Basic ${encodedCredentials}`);
|
|
61
|
+
const tokens = await sendTokenRequest(request);
|
|
62
|
+
return tokens;
|
|
63
|
+
}
|
|
64
|
+
async getAuthorizationURL(scopes) {
|
|
65
|
+
const auth = requireAuthConfig(this.auth);
|
|
66
|
+
const state = generateOAuthState();
|
|
67
|
+
const url = this.createAuthorizationURL(state, resolveScopes(scopes, auth, defaultScopes));
|
|
68
|
+
await saveOAuthState(auth.store, state, {});
|
|
69
|
+
return url;
|
|
70
|
+
}
|
|
71
|
+
async getUser(query) {
|
|
72
|
+
const auth = requireAuthConfig(this.auth);
|
|
73
|
+
const { code, state } = parseCallbackQuery(query);
|
|
74
|
+
await consumeOAuthState(auth.store, state);
|
|
75
|
+
const tokens = await this.validateAuthorizationCode(code);
|
|
76
|
+
const accessToken = tokens.accessToken();
|
|
77
|
+
const profile = await fetchUserProfile(userEndpoint, accessToken);
|
|
78
|
+
let email = profileString(profile.email);
|
|
79
|
+
if (email === null) {
|
|
80
|
+
email = await fetchPrimaryEmail(accessToken);
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
id: profileId(profile.id),
|
|
84
|
+
name: profileString(profile.name) ?? profileString(profile.login),
|
|
85
|
+
email,
|
|
86
|
+
image: profileString(profile.avatar_url)
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Private emails are not included in the profile and need the user:email scope.
|
|
91
|
+
async function fetchPrimaryEmail(accessToken) {
|
|
92
|
+
let emails;
|
|
93
|
+
try {
|
|
94
|
+
emails = await fetchUserProfile(userEmailsEndpoint, accessToken);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
if (!Array.isArray(emails)) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const entries = emails.filter((entry) => typeof entry === "object" && entry !== null && typeof entry.email === "string");
|
|
103
|
+
const primary = entries.find((entry) => entry.primary === true);
|
|
104
|
+
return primary?.email ?? entries[0]?.email ?? null;
|
|
105
|
+
}
|
|
106
|
+
async function sendTokenRequest(request) {
|
|
107
|
+
let response;
|
|
108
|
+
try {
|
|
109
|
+
response = await fetch(request);
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
throw new ArcticFetchError(e);
|
|
113
|
+
}
|
|
114
|
+
if (response.status !== 200) {
|
|
115
|
+
if (response.body !== null) {
|
|
116
|
+
await response.body.cancel();
|
|
117
|
+
}
|
|
118
|
+
throw new UnexpectedResponseError(response.status);
|
|
119
|
+
}
|
|
120
|
+
let data;
|
|
121
|
+
try {
|
|
122
|
+
data = await response.json();
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
throw new UnexpectedResponseError(response.status);
|
|
126
|
+
}
|
|
127
|
+
if (typeof data !== "object" || data === null) {
|
|
128
|
+
throw new UnexpectedErrorResponseBodyError(response.status, data);
|
|
129
|
+
}
|
|
130
|
+
if ("error" in data && typeof data.error === "string") {
|
|
131
|
+
let error;
|
|
132
|
+
try {
|
|
133
|
+
error = createOAuth2RequestError(data);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
throw new UnexpectedErrorResponseBodyError(response.status, data);
|
|
137
|
+
}
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
const tokens = new OAuth2Tokens(data);
|
|
141
|
+
return tokens;
|
|
142
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface GitLabOptions extends ProviderOptions {
|
|
4
|
+
baseURL?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class GitLab {
|
|
7
|
+
private authorizationEndpoint;
|
|
8
|
+
private tokenEndpoint;
|
|
9
|
+
private tokenRevocationEndpoint;
|
|
10
|
+
private baseURL;
|
|
11
|
+
private client;
|
|
12
|
+
private auth;
|
|
13
|
+
constructor(options: GitLabOptions);
|
|
14
|
+
constructor(baseURL: string, clientId: string, clientSecret: string | null, redirectURI: string);
|
|
15
|
+
createAuthorizationURL(state: string, scopes: string[]): URL;
|
|
16
|
+
validateAuthorizationCode(code: 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,64 @@
|
|
|
1
|
+
import { OAuth2Client } from "../client.js";
|
|
2
|
+
import { joinURIAndPath } from "../request.js";
|
|
3
|
+
import { consumeOAuthState, fetchUserProfile, generateOAuthState, parseCallbackQuery, profileId, profileString, requireAuthConfig, requireProviderOption, resolveAuthConfig, resolveScopes, saveOAuthState } from "../auth.js";
|
|
4
|
+
const envPrefix = "GITLAB";
|
|
5
|
+
const defaultScopes = ["openid", "profile", "email"];
|
|
6
|
+
export class GitLab {
|
|
7
|
+
authorizationEndpoint;
|
|
8
|
+
tokenEndpoint;
|
|
9
|
+
tokenRevocationEndpoint;
|
|
10
|
+
baseURL;
|
|
11
|
+
client;
|
|
12
|
+
auth = null;
|
|
13
|
+
constructor(baseURLOrOptions, clientId, clientSecret, redirectURI) {
|
|
14
|
+
if (typeof baseURLOrOptions === "object") {
|
|
15
|
+
this.auth = resolveAuthConfig(envPrefix, baseURLOrOptions, { redirectURI: true });
|
|
16
|
+
this.baseURL = requireProviderOption(baseURLOrOptions.baseURL, envPrefix, "BASE_URL", "baseURL");
|
|
17
|
+
this.client = new OAuth2Client(this.auth.clientId, this.auth.clientSecret, this.auth.redirectURI);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
this.baseURL = baseURLOrOptions;
|
|
21
|
+
this.client = new OAuth2Client(clientId ?? "", clientSecret ?? null, redirectURI ?? null);
|
|
22
|
+
}
|
|
23
|
+
this.authorizationEndpoint = joinURIAndPath(this.baseURL, "/oauth/authorize");
|
|
24
|
+
this.tokenEndpoint = joinURIAndPath(this.baseURL, "/oauth/token");
|
|
25
|
+
this.tokenRevocationEndpoint = joinURIAndPath(this.baseURL, "/oauth/revoke");
|
|
26
|
+
}
|
|
27
|
+
createAuthorizationURL(state, scopes) {
|
|
28
|
+
const url = this.client.createAuthorizationURL(this.authorizationEndpoint, state, scopes);
|
|
29
|
+
return url;
|
|
30
|
+
}
|
|
31
|
+
async validateAuthorizationCode(code) {
|
|
32
|
+
const tokens = await this.client.validateAuthorizationCode(this.tokenEndpoint, code, null);
|
|
33
|
+
return tokens;
|
|
34
|
+
}
|
|
35
|
+
async refreshAccessToken(refreshToken) {
|
|
36
|
+
const tokens = await this.client.refreshAccessToken(this.tokenEndpoint, refreshToken, []);
|
|
37
|
+
return tokens;
|
|
38
|
+
}
|
|
39
|
+
async revokeToken(token) {
|
|
40
|
+
await this.client.revokeToken(this.tokenRevocationEndpoint, token);
|
|
41
|
+
}
|
|
42
|
+
async getAuthorizationURL(scopes) {
|
|
43
|
+
const auth = requireAuthConfig(this.auth);
|
|
44
|
+
const state = generateOAuthState();
|
|
45
|
+
const url = this.createAuthorizationURL(state, resolveScopes(scopes, auth, defaultScopes));
|
|
46
|
+
await saveOAuthState(auth.store, state, {});
|
|
47
|
+
return url;
|
|
48
|
+
}
|
|
49
|
+
async getUser(query) {
|
|
50
|
+
const auth = requireAuthConfig(this.auth);
|
|
51
|
+
const { code, state } = parseCallbackQuery(query);
|
|
52
|
+
await consumeOAuthState(auth.store, state);
|
|
53
|
+
const tokens = await this.validateAuthorizationCode(code);
|
|
54
|
+
// GitLab id_tokens omit profile claims, so always use the OIDC userinfo endpoint.
|
|
55
|
+
const userinfoEndpoint = joinURIAndPath(this.baseURL, "/oauth/userinfo");
|
|
56
|
+
const claims = await fetchUserProfile(userinfoEndpoint, tokens.accessToken());
|
|
57
|
+
return {
|
|
58
|
+
id: profileId(claims.sub),
|
|
59
|
+
name: profileString(claims.name) ?? profileString(claims.nickname),
|
|
60
|
+
email: profileString(claims.email),
|
|
61
|
+
image: profileString(claims.picture)
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { OAuth2Tokens } from "../oauth2.js";
|
|
2
|
+
import type { OAuthCallbackQuery, OAuthUser, ProviderOptions } from "../auth.js";
|
|
3
|
+
export interface GoogleOptions extends ProviderOptions {
|
|
4
|
+
}
|
|
5
|
+
export declare class Google {
|
|
6
|
+
private client;
|
|
7
|
+
private auth;
|
|
8
|
+
constructor(options: GoogleOptions);
|
|
9
|
+
constructor(clientId: string, clientSecret: string, 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
|
+
}
|