Socket
Socket
Sign inDemoInstall

arctic

Package Overview
Dependencies
37
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.7.1 to 0.8.0

dist/providers/atlassian.d.ts

56

dist/index.d.ts
export { Apple } from "./providers/apple.js";
export { Atlassian } from "./providers/atlassian.js";
export { Auth0 } from "./providers/auth0.js";
export { Bitbucket } from "./providers/bitbucket.js";
export { Box } from "./providers/box.js";
export { Discord } from "./providers/discord.js";
export { Dropbox } from "./providers/dropbox.js";
export { Facebook } from "./providers/facebook.js";

@@ -13,3 +16,3 @@ export { Figma } from "./providers/figma.js";

export { LinkedIn } from "./providers/linkedin.js";
export { MicrosoftEntraID } from "./providers/microsoft-entra-id.js";
export { MicrosoftEntraId } from "./providers/microsoft-entra-id.js";
export { Notion } from "./providers/notion.js";

@@ -21,22 +24,27 @@ export { Reddit } from "./providers/reddit.js";

export { Twitter } from "./providers/twitter.js";
export type { AppleCredentials, AppleIdTokenClaims, AppleRefreshedTokens, AppleTokens } from "./providers/apple.js";
export type { Auth0Tokens, Auth0User } from "./providers/auth0.js";
export type { BitbucketLink, BitbucketLinks, BitbucketTokens, BitbucketUser } from "./providers/bitbucket.js";
export type { DiscordTokens, DiscordUser } from "./providers/discord.js";
export type { FacebookTokens, FacebookUser } from "./providers/facebook.js";
export type { FigmaRefreshedTokens, FigmaTokens, FigmaUser } from "./providers/figma.js";
export type { GitHubTokens, GitHubUser, PrivateGitHubUser, PublicGitHubUser } from "./providers/github.js";
export type { GitLabTokens, GitLabUser } from "./providers/gitlab.js";
export type { GoogleRefreshedTokens, GoogleTokens, GoogleUser } from "./providers/google.js";
export type { KakaoAccount, KakaoPartner, KakaoProfile, KakaoTokens, KakaoUser } from "./providers/kakao.js";
export type { KeycloakTokens, KeycloakUser } from "./providers/keycloak.js";
export type { LineRefreshedTokens, LineTokens, LineUser } from "./providers/line.js";
export type { LinkedInTokens, LinkedInUser } from "./providers/linkedin.js";
export type { MicrosoftEntraIDIdTokenClaims, MicrosoftEntraIDTokens, MicrosoftEntraIDUser } from "./providers/microsoft-entra-id.js";
export type { NotionPersonUser, NotionTokens, NotionUser } from "./providers/notion.js";
export type { RedditTokens, RedditUser } from "./providers/reddit.js";
export type { SlackTokens, SlackUser } from "./providers/slack.js";
export type { SpotifyTokens, SpotifyUser } from "./providers/spotify.js";
export type { TwitchTokens, TwitchUser } from "./providers/twitch.js";
export type { TwitterTokens, TwitterUser } from "./providers/twitter.js";
export { Yahoo } from "./providers/yahoo.js";
export type { AppleCredentials, AppleRefreshedTokens, AppleTokens } from "./providers/apple.js";
export type { AtlassianTokens } from "./providers/atlassian.js";
export type { Auth0Tokens } from "./providers/auth0.js";
export type { BitbucketTokens } from "./providers/bitbucket.js";
export type { BoxTokens } from "./providers/box.js";
export type { DiscordTokens } from "./providers/discord.js";
export type { DropboxRefreshedTokens, DropboxTokens } from "./providers/dropbox.js";
export type { FacebookTokens } from "./providers/facebook.js";
export type { FigmaRefreshedTokens, FigmaTokens } from "./providers/figma.js";
export type { GitHubTokens } from "./providers/github.js";
export type { GitLabTokens } from "./providers/gitlab.js";
export type { GoogleRefreshedTokens, GoogleTokens } from "./providers/google.js";
export type { KakaoTokens } from "./providers/kakao.js";
export type { KeycloakTokens } from "./providers/keycloak.js";
export type { LineRefreshedTokens, LineTokens } from "./providers/line.js";
export type { LinkedInTokens } from "./providers/linkedin.js";
export type { MicrosoftEntraIdTokens } from "./providers/microsoft-entra-id.js";
export type { NotionTokens } from "./providers/notion.js";
export type { RedditTokens } from "./providers/reddit.js";
export type { SlackTokens } from "./providers/slack.js";
export type { SpotifyTokens } from "./providers/spotify.js";
export type { TwitchTokens } from "./providers/twitch.js";
export type { TwitterTokens } from "./providers/twitter.js";
export type { YahooTokens } from "./providers/yahoo.js";
export { generateCodeVerifier, generateState, OAuth2RequestError } from "oslo/oauth2";

@@ -47,3 +55,2 @@ export interface OAuth2Provider {

refreshAccessToken?(refreshToken: string): Promise<Tokens>;
getUser?(accessToken: string): Promise<{}>;
}

@@ -54,6 +61,9 @@ export interface OAuth2ProviderWithPKCE {

refreshAccessToken?(refreshToken: string): Promise<Tokens>;
getUser?(accessToken: string): Promise<{}>;
}
export interface Tokens {
accessToken: string;
refreshToken?: string | null;
accessTokenExpiresAt?: Date;
refreshTokenExpiresAt?: Date | null;
idToken?: string;
}
export { Apple } from "./providers/apple.js";
export { Atlassian } from "./providers/atlassian.js";
export { Auth0 } from "./providers/auth0.js";
export { Bitbucket } from "./providers/bitbucket.js";
export { Box } from "./providers/box.js";
export { Discord } from "./providers/discord.js";
export { Dropbox } from "./providers/dropbox.js";
export { Facebook } from "./providers/facebook.js";

@@ -13,3 +16,3 @@ export { Figma } from "./providers/figma.js";

export { LinkedIn } from "./providers/linkedin.js";
export { MicrosoftEntraID } from "./providers/microsoft-entra-id.js";
export { MicrosoftEntraId } from "./providers/microsoft-entra-id.js";
export { Notion } from "./providers/notion.js";

@@ -21,2 +24,3 @@ export { Reddit } from "./providers/reddit.js";

export { Twitter } from "./providers/twitter.js";
export { Yahoo } from "./providers/yahoo.js";
export { generateCodeVerifier, generateState, OAuth2RequestError } from "oslo/oauth2";
import type { OAuth2Provider } from "../index.js";
export declare class Apple implements OAuth2Provider {
private client;
private scope;
private credentials;
constructor(credentials: AppleCredentials, redirectURI: string, options?: {
constructor(credentials: AppleCredentials, redirectURI: string);
createAuthorizationURL(state: string, options?: {
responseMode?: "query" | "form_post";
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<AppleTokens>;
refreshAccessToken(refreshToken: string): Promise<AppleRefreshedTokens>;
private createClientSecret;
private parseIdToken;
}
export interface AppleIdTokenClaims {
iss: "https://appleid.apple.com";
sub: string;
aud: string;
iat: number;
exp: number;
email?: string;
email_verified?: boolean;
is_private_email?: boolean;
real_user_status: 0 | 1 | 2;
transfer_sub?: string;
nonce?: string;
nonce_supported?: boolean;
}
export interface AppleTokens {

@@ -35,3 +19,2 @@ accessToken: string;

idToken: string;
idTokenClaims: AppleIdTokenClaims;
}

@@ -42,3 +25,2 @@ export interface AppleRefreshedTokens {

idToken: string;
idTokenClaims: AppleIdTokenClaims;
}

@@ -45,0 +27,0 @@ export interface AppleCredentials {

import { TimeSpan, createDate } from "oslo";
import { decodeBase64 } from "oslo/encoding";
import { createJWT, parseJWT } from "oslo/jwt";
import { createJWT } from "oslo/jwt";
import { OAuth2Client } from "oslo/oauth2";

@@ -9,17 +9,16 @@ const authorizeEndpoint = "https://appleid.apple.com/auth/authorize";

client;
scope;
credentials;
constructor(credentials, redirectURI, options) {
constructor(credentials, redirectURI) {
this.client = new OAuth2Client(credentials.clientId, authorizeEndpoint, tokenEndpoint, {
redirectURI,
responseMode: options?.responseMode
redirectURI
});
this.credentials = credentials;
this.scope = options?.scope ?? [];
}
async createAuthorizationURL(state) {
return await this.client.createAuthorizationURL({
async createAuthorizationURL(state, options) {
const url = await this.client.createAuthorizationURL({
state,
scope: this.scope
scope: options?.scope ?? []
});
url.searchParams.set("response_mode", options?.responseMode ?? "query");
return url;
}

@@ -31,9 +30,9 @@ async validateAuthorizationCode(code) {

});
return {
const tokens = {
accessToken: result.access_token,
refreshToken: result.refresh_token ?? null,
accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),
idToken: result.id_token,
idTokenClaims: this.parseIdToken(result.id_token)
idToken: result.id_token
};
return tokens;
}

@@ -45,8 +44,8 @@ async refreshAccessToken(refreshToken) {

});
return {
const tokens = {
accessToken: result.access_token,
accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),
idToken: result.id_token,
idTokenClaims: this.parseIdToken(result.id_token)
idToken: result.id_token
};
return tokens;
}

@@ -68,8 +67,2 @@ async createClientSecret() {

}
parseIdToken(idToken) {
const parsedIdToken = parseJWT(idToken);
if (!parsedIdToken)
throw new Error("Failed to parse ID token");
return parsedIdToken.payload;
}
}

@@ -76,0 +69,0 @@ function parsePKCS8PEM(pkcs8) {

@@ -6,9 +6,7 @@ import type { OAuth2Provider } from "../index.js";

private clientSecret;
private scope;
constructor(appDomain: string, clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(appDomain: string, clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<Auth0Tokens>;
getUser(accessToken: string): Promise<Auth0User>;
refreshAccessToken(refreshToken: string): Promise<Auth0Tokens>;

@@ -21,21 +19,1 @@ }

}
export interface Auth0User {
sub: string;
name: string;
picture: string;
locale: string;
updated_at: string;
given_name?: string;
family_name?: string;
middle_name?: string;
nickname?: string;
preferred_username?: string;
profile?: string;
email?: string;
email_verified?: boolean;
gender?: string;
birthdate?: string;
zoneinfo?: string;
phone_number?: string;
phone_number_verified?: boolean;
}

@@ -6,4 +6,3 @@ import { OAuth2Client } from "oslo/oauth2";

clientSecret;
scope;
constructor(appDomain, clientId, clientSecret, redirectURI, options) {
constructor(appDomain, clientId, clientSecret, redirectURI) {
this.appDomain = appDomain;

@@ -16,9 +15,9 @@ const authorizeEndpoint = this.appDomain + "/authorize";

this.clientSecret = clientSecret;
this.scope = options?.scope ?? [];
this.scope.push("openid", "profile");
}
async createAuthorizationURL(state) {
async createAuthorizationURL(state, options) {
const scope = options?.scope ?? [];
scope.push("openid");
return await this.client.createAuthorizationURL({
scope: this.scope,
state
state,
scope: options?.scope ?? []
});

@@ -31,3 +30,3 @@ }

});
return {
const tokens = {
accessToken: result.access_token,

@@ -37,12 +36,4 @@ refreshToken: result.refresh_token,

};
return tokens;
}
async getUser(accessToken) {
const userinfoEndpoint = this.appDomain + "/userinfo";
const response = await fetch(userinfoEndpoint, {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {

@@ -53,3 +44,3 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,

@@ -59,3 +50,4 @@ refreshToken: result.refresh_token,

};
return tokens;
}
}

@@ -5,9 +5,7 @@ import type { OAuth2Provider } from "../index.js";

private clientSecret;
private scope;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<BitbucketTokens>;
getUser(accessToken: string): Promise<BitbucketUser>;
refreshAccessToken(refreshToken: string): Promise<BitbucketTokens>;

@@ -20,16 +18,1 @@ }

}
export interface BitbucketUser {
type: string;
links: BitbucketLinks;
created_on: string;
display_name: string;
username: string;
uuid: string;
}
export interface BitbucketLinks {
avatar: BitbucketLink;
}
export interface BitbucketLink {
href: string;
name: string;
}

@@ -5,8 +5,6 @@ import { OAuth2Client } from "oslo/oauth2";

const tokenEndpoint = "https://bitbucket.org/site/oauth2/access_token";
const userEndpoint = "https://api.bitbucket.org/2.0/user";
export class Bitbucket {
client;
clientSecret;
scope;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {

@@ -16,9 +14,7 @@ redirectURI

this.clientSecret = clientSecret;
this.scope = options?.scope ?? [];
this.scope.push("account");
}
async createAuthorizationURL(state) {
async createAuthorizationURL(state, options) {
return await this.client.createAuthorizationURL({
scope: this.scope,
state
state,
scope: options?.scope ?? []
});

@@ -30,3 +26,3 @@ }

});
return {
const tokens = {
accessToken: result.access_token,

@@ -36,11 +32,4 @@ accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),

};
return tokens;
}
async getUser(accessToken) {
const response = await fetch(userEndpoint, {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {

@@ -50,3 +39,3 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,

@@ -56,3 +45,4 @@ accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),

};
return tokens;
}
}
import type { OAuth2Provider } from "../index.js";
export declare class Discord implements OAuth2Provider {
private client;
private scope;
private clientSecret;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<DiscordTokens>;
getUser(accessToken: string): Promise<DiscordUser>;
refreshAccessToken(refreshToken: string): Promise<DiscordTokens>;

@@ -19,20 +17,1 @@ }

}
export interface DiscordUser {
id: string;
username: string;
discriminator: string;
global_name: string | null;
avatar: string | null;
bot?: boolean;
system?: boolean;
mfa_enabled?: boolean;
verified?: boolean;
email?: string | null;
flags?: number;
banner?: string | null;
accent_color?: number | null;
premium_type?: number;
public_flags?: number;
locale?: string;
avatar_decoration?: string | null;
}

@@ -0,3 +1,3 @@

import { OAuth2Client } from "oslo/oauth2";
import { TimeSpan, createDate } from "oslo";
import { OAuth2Client } from "oslo/oauth2";
const authorizeEndpoint = "https://discord.com/oauth2/authorize";

@@ -7,16 +7,13 @@ const tokenEndpoint = "https://discord.com/api/oauth2/token";

client;
scope;
clientSecret;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {
redirectURI
});
this.scope = options?.scope ?? [];
this.scope.push("identify");
this.clientSecret = clientSecret;
}
async createAuthorizationURL(state) {
async createAuthorizationURL(state, options) {
return await this.client.createAuthorizationURL({
state,
scope: this.scope
scope: options?.scope ?? []
});

@@ -29,3 +26,3 @@ }

});
return {
const tokens = {
accessToken: result.access_token,

@@ -35,11 +32,4 @@ refreshToken: result.refresh_token,

};
return tokens;
}
async getUser(accessToken) {
const response = await fetch("https://discord.com/api/users/@me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {

@@ -50,3 +40,3 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,

@@ -56,3 +46,4 @@ refreshToken: result.refresh_token,

};
return tokens;
}
}
import type { OAuth2Provider } from "../index.js";
export declare class Facebook implements OAuth2Provider {
private client;
private scope;
private clientSecret;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<FacebookTokens>;
getUser(accessToken: string): Promise<FacebookUser>;
}

@@ -17,14 +15,1 @@ export interface FacebookTokens {

}
export interface FacebookUser {
id: string;
name: string;
email?: string;
picture: {
data: {
height: number;
is_silhouette: boolean;
url: string;
width: number;
};
};
}

@@ -7,15 +7,13 @@ import { OAuth2Client } from "oslo/oauth2";

client;
scope;
clientSecret;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {
redirectURI
});
this.scope = options?.scope ?? [];
this.clientSecret = clientSecret;
}
async createAuthorizationURL(state) {
async createAuthorizationURL(state, options) {
return await this.client.createAuthorizationURL({
state,
scope: this.scope
scope: options?.scope
});

@@ -28,18 +26,8 @@ }

});
return {
const tokens = {
accessToken: result.access_token,
accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s"))
};
return tokens;
}
async getUser(accessToken) {
const url = new URL("https://graph.facebook.com/me");
url.searchParams.set("access_token", accessToken);
url.searchParams.set("fields", ["id", "name", "picture", "email"].join(","));
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
}
import type { OAuth2Provider } from "../index.js";
export declare class Figma implements OAuth2Provider {
private client;
private scope;
private clientSecret;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<FigmaTokens>;
getUser(accessToken: string): Promise<FigmaUser>;
refreshAccessToken(refreshToken: string): Promise<FigmaRefreshedTokens>;

@@ -24,7 +22,1 @@ }

}
export interface FigmaUser {
id: string;
handle: string;
img_url: string;
email: string;
}
import { TimeSpan, createDate } from "oslo";
import { OAuth2Client } from "oslo/oauth2";
import { sendRequest } from "../request.js";
const authorizeEndpoint = "https://www.figma.com/oauth";
const tokenEndpoint = "https://www.figma.com/api/oauth/token";
const userEndpoint = "https://api.figma.com/v1/me";
export class Figma {
client;
scope;
clientSecret;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {
redirectURI
});
this.scope = options?.scope ?? [];
this.clientSecret = clientSecret;
}
async createAuthorizationURL(state) {
async createAuthorizationURL(state, options) {
const url = await this.client.createAuthorizationURL({
scope: this.scope,
state
state,
scope: options?.scope ?? []
});

@@ -30,3 +26,3 @@ return url;

});
return {
const tokens = {
accessToken: result.access_token,

@@ -37,8 +33,4 @@ refreshToken: result.refresh_token ?? null,

};
return tokens;
}
async getUser(accessToken) {
const request = new Request(userEndpoint);
request.headers.set("Authorization", `Bearer ${accessToken}`);
return await sendRequest(request);
}
async refreshAccessToken(refreshToken) {

@@ -49,7 +41,8 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,
accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s"))
};
return tokens;
}
}
import type { OAuth2Provider } from "../index.js";
export declare class GitHub implements OAuth2Provider {
private client;
private scope;
private clientSecret;
constructor(clientId: string, clientSecret: string, options?: {
redirectURI?: string;
});
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<GitHubTokens>;
getUser(accessToken: string): Promise<GitHubUser>;
}

@@ -17,53 +16,1 @@ export interface GitHubTokens {

}
export type GitHubUser = PublicGitHubUser | PrivateGitHubUser;
export interface PublicGitHubUser {
avatar_url: string;
bio: string | null;
blog: string | null;
company: string | null;
created_at: string;
email: string | null;
events_url: string;
followers: number;
followers_url: string;
following: number;
following_url: string;
gists_url: string;
gravatar_id: string | null;
hireable: boolean | null;
html_url: string;
id: number;
location: string | null;
login: string;
name: string | null;
node_id: string;
organizations_url: string;
public_gists: number;
public_repos: number;
received_events_url: string;
repos_url: string;
site_admin: boolean;
starred_url: string;
subscriptions_url: string;
type: string;
updated_at: string;
url: string;
twitter_username?: string | null;
plan?: {
name: string;
space: number;
private_repos: number;
collaborators: number;
};
suspended_at?: string | null;
}
export interface PrivateGitHubUser extends PublicGitHubUser {
collaborators: number;
disk_usage: number;
owned_private_repos: number;
private_gists: number;
total_private_repos: number;
two_factor_authentication: boolean;
business_plus?: boolean;
ldap_dn?: string;
}

@@ -6,3 +6,2 @@ import { OAuth2Client } from "oslo/oauth2";

client;
scope;
clientSecret;

@@ -13,9 +12,8 @@ constructor(clientId, clientSecret, options) {

});
this.scope = options?.scope ?? [];
this.clientSecret = clientSecret;
}
async createAuthorizationURL(state) {
async createAuthorizationURL(state, options) {
return await this.client.createAuthorizationURL({
state,
scope: this.scope
scope: options?.scope ?? []
});

@@ -28,14 +26,7 @@ }

});
return {
const tokens = {
accessToken: result.access_token
};
return tokens;
}
async getUser(accessToken) {
const response = await fetch("https://api.github.com/user", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
}

@@ -5,11 +5,9 @@ import type { OAuth2Provider } from "../index.js";

private clientSecret;
private scope;
private domain;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
domain?: string;
});
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<GitLabTokens>;
getUser(accessToken: string): Promise<GitLabUser>;
refreshAccessToken(refreshToken: string): Promise<GitLabTokens>;

@@ -22,43 +20,1 @@ }

}
export interface GitLabUser {
id: number;
username: string;
email: string;
name: string;
state: string;
avatar_url: string;
web_url: string;
created_at: string;
bio: string;
public_email: string;
skype: string;
linkedin: string;
twitter: string;
discord: string;
website_url: string;
organization: string;
job_title: string;
pronouns: string;
bot: boolean;
work_information: string | null;
followers: number;
following: number;
local_time: string;
last_sign_in_at: string;
confirmed_at: string;
theme_id: number;
last_activity_on: string;
color_scheme_id: number;
projects_limit: number;
current_sign_in_at: string;
identities: {
provider: string;
extern_uid: string;
}[];
can_create_group: boolean;
can_create_project: boolean;
two_factor_enabled: boolean;
external: boolean;
private_profile: boolean;
commit_email: string;
}

@@ -6,8 +6,6 @@ import { OAuth2Client } from "oslo/oauth2";

clientSecret;
scope;
domain;
constructor(clientId, clientSecret, redirectURI, options) {
this.domain = options?.domain ?? "https://gitlab.com";
const authorizeEndpoint = this.domain + "/oauth/authorize";
const tokenEndpoint = this.domain + "/oauth/token";
const domain = options?.domain ?? "https://gitlab.com";
const authorizeEndpoint = domain + "/oauth/authorize";
const tokenEndpoint = domain + "/oauth/token";
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {

@@ -17,9 +15,7 @@ redirectURI

this.clientSecret = clientSecret;
this.scope = options?.scope ?? [];
this.scope.push("read_user");
}
async createAuthorizationURL(state) {
async createAuthorizationURL(state, options) {
return await this.client.createAuthorizationURL({
scope: this.scope,
state
state,
scope: options?.scope ?? []
});

@@ -32,3 +28,3 @@ }

});
return {
const tokens = {
accessToken: result.access_token,

@@ -38,11 +34,4 @@ accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),

};
return tokens;
}
async getUser(accessToken) {
const response = await fetch(this.domain + "/api/v4/user", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {

@@ -53,3 +42,3 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,

@@ -59,3 +48,4 @@ accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),

};
return tokens;
}
}
import type { OAuth2ProviderWithPKCE } from "../index.js";
export declare class Google implements OAuth2ProviderWithPKCE {
private client;
private scope;
private clientSecret;
private accessType;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(codeVerifier: string, options?: {
scope?: string[];
accessType?: "online" | "offline";
});
createAuthorizationURL(codeVerifier: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string, codeVerifier: string): Promise<GoogleTokens>;
getUser(accessToken: string): Promise<GoogleUser>;
refreshAccessToken(refreshToken: string): Promise<GoogleRefreshedTokens>;

@@ -26,12 +23,1 @@ }

}
export interface GoogleUser {
sub: string;
name: string;
given_name: string;
family_name: string;
picture: string;
locale: string;
email?: string;
email_verified?: boolean;
hd?: string;
}
import { TimeSpan, createDate } from "oslo";
import { OAuth2Client } from "oslo/oauth2";
import { sendRequest } from "../request.js";
const authorizeEndpoint = "https://accounts.google.com/o/oauth2/v2/auth";
const tokenEndpoint = "https://oauth2.googleapis.com/token";
const userinfoEndpoint = "https://openidconnect.googleapis.com/v1/userinfo";
export class Google {
client;
scope;
clientSecret;
accessType;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {
redirectURI
});
this.scope = options?.scope ?? [];
this.scope.push("openid", "profile");
this.clientSecret = clientSecret;
this.accessType = options?.accessType ?? "online";
}
async createAuthorizationURL(codeVerifier) {
async createAuthorizationURL(codeVerifier, options) {
const scope = options?.scope ?? [];
scope.push("openid");
const url = await this.client.createAuthorizationURL({
scope: this.scope,
codeVerifier
codeVerifier,
scope
});
url.searchParams.set("access_type", this.accessType);
url.searchParams.set("access_type", options?.accessType ?? "online");
return url;

@@ -35,3 +30,3 @@ }

});
return {
const tokens = {
accessToken: result.access_token,

@@ -42,8 +37,4 @@ refreshToken: result.refresh_token ?? null,

};
return tokens;
}
async getUser(accessToken) {
const request = new Request(userinfoEndpoint);
request.headers.set("Authorization", `Bearer ${accessToken}`);
return await sendRequest(request);
}
async refreshAccessToken(refreshToken) {

@@ -54,7 +45,8 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,
accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s"))
};
return tokens;
}
}

@@ -1,12 +0,10 @@

import type { OAuth2ProviderWithPKCE } from "../index.js";
export declare class Kakao implements OAuth2ProviderWithPKCE {
import type { OAuth2Provider } from "../index.js";
export declare class Kakao implements OAuth2Provider {
private client;
private scope;
private clientSecret;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(codeVerifier: string): Promise<URL>;
validateAuthorizationCode(code: string, codeVerifier: string): Promise<KakaoTokens>;
getUser(accessToken: string): Promise<KakaoUser>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<KakaoTokens>;
refreshAccessToken(refreshToken: string): Promise<KakaoTokens>;

@@ -20,45 +18,1 @@ }

}
export interface KakaoUser {
id: number;
has_signed_up?: boolean;
connected_at?: string;
synced_at?: string;
properties?: Record<string, string>;
kakao_account?: KakaoAccount;
for_partner?: KakaoPartner;
}
export interface KakaoAccount {
profile_needs_agreement?: boolean;
profile_nickname_needs_agreement?: boolean;
profile_image_needs_agreement?: boolean;
profile?: KakaoProfile;
email_needs_agreement?: boolean;
is_email_valid?: boolean;
is_email_verified?: boolean;
email?: string;
name_needs_agreement?: boolean;
name?: string;
age_range_needs_agreement?: boolean;
ag_range?: "1~9" | "10~14" | "15~19" | "20~29" | "30~39" | "40~49" | "50~59" | "60~69" | "70~79" | "80~89" | "90~";
birthyear_needs_agreement?: boolean;
birthyear?: string;
birthday_needs_agreement?: boolean;
birthday?: string;
birthday_type?: "SOLAR" | "LUNAR";
gender_needs_agreement?: boolean;
gender?: "female" | "male";
phone_number_needs_agreement?: boolean;
phone_number?: string;
ci_needs_agreement?: boolean;
ci?: string;
ci_authenticated_at?: string;
}
export interface KakaoProfile {
nickname?: string;
thumbnail_image_url?: string;
profile_image_url?: string;
is_default_image?: boolean;
}
export interface KakaoPartner {
uuid?: string;
}

@@ -7,24 +7,21 @@ import { TimeSpan, createDate } from "oslo";

client;
scope;
clientSecret;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {
redirectURI
});
this.scope = options?.scope ?? [];
this.clientSecret = clientSecret;
}
async createAuthorizationURL(codeVerifier) {
async createAuthorizationURL(state, options) {
return await this.client.createAuthorizationURL({
codeVerifier,
scope: this.scope
state,
scope: options?.scope ?? []
});
}
async validateAuthorizationCode(code, codeVerifier) {
async validateAuthorizationCode(code) {
const result = await this.client.validateAuthorizationCode(code, {
authenticateWith: "request_body",
credentials: this.clientSecret,
codeVerifier
credentials: this.clientSecret
});
return {
const tokens = {
accessToken: result.access_token,

@@ -35,11 +32,4 @@ accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),

};
return tokens;
}
async getUser(accessToken) {
const response = await fetch("https://kapi.kakao.com/v2/user/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {

@@ -50,3 +40,3 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,

@@ -57,3 +47,4 @@ accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),

};
return tokens;
}
}

@@ -6,9 +6,7 @@ import type { OAuth2ProviderWithPKCE } from "../index.js";

private clientSecret;
private scope;
constructor(realmURL: string, clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(realmURL: string, clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(codeVerifier: string, options?: {
scope?: string[];
});
createAuthorizationURL(codeVerifier: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string, codeVerifier: string): Promise<KeycloakTokens>;
getUser(accessToken: string): Promise<KeycloakUser>;
refreshAccessToken(refreshToken: string): Promise<KeycloakTokens>;

@@ -23,25 +21,1 @@ }

}
export interface KeycloakUser {
exp: number;
iat: number;
auth_time: number;
jti: string;
iss: string;
aud: string;
sub: string;
typ: string;
azp: string;
session_state: string;
at_hash: string;
acr: string;
sid: string;
email_verified: boolean;
name: string;
preferred_username: string;
given_name: string;
locale: string;
family_name: string;
email: string;
picture: string;
user: any;
}

@@ -7,4 +7,3 @@ import { OAuth2Client } from "oslo/oauth2";

clientSecret;
scope;
constructor(realmURL, clientId, clientSecret, redirectURI, options) {
constructor(realmURL, clientId, clientSecret, redirectURI) {
this.realmURL = realmURL;

@@ -17,9 +16,9 @@ const authorizeEndpoint = this.realmURL + "/protocol/openid-connect/auth";

this.clientSecret = clientSecret;
this.scope = options?.scope ?? [];
this.scope.push("openid", "profile");
}
async createAuthorizationURL(codeVerifier) {
async createAuthorizationURL(codeVerifier, options) {
const scope = options?.scope ?? [];
scope.push("openid");
return await this.client.createAuthorizationURL({
scope: this.scope,
codeVerifier
codeVerifier,
scope
});

@@ -33,3 +32,3 @@ }

});
return {
const tokens = {
accessToken: result.access_token,

@@ -41,12 +40,4 @@ accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),

};
return tokens;
}
async getUser(accessToken) {
const userinfoEndpoint = this.realmURL + "/protocol/openid-connect/userinfo";
const response = await fetch(userinfoEndpoint, {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {

@@ -57,3 +48,3 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,

@@ -65,3 +56,4 @@ accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),

};
return tokens;
}
}
import type { OAuth2ProviderWithPKCE } from "../index.js";
export declare class Line implements OAuth2ProviderWithPKCE {
private client;
private scope;
private clientSecret;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(codeVerifier: string, options?: {
scope?: string[];
});
createAuthorizationURL(codeVerifier: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string, codeVerifier: string): Promise<LineTokens>;
getUser(accessToken: string): Promise<LineUser>;
refreshAccessToken(refreshToken: string): Promise<LineRefreshedTokens>;

@@ -25,6 +23,1 @@ }

}
export interface LineUser {
sub: string;
name: string;
picture: string;
}

@@ -7,17 +7,16 @@ import { OAuth2Client, generateState } from "oslo/oauth2";

client;
scope;
clientSecret;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {
redirectURI
});
this.scope = options?.scope ?? [];
this.scope.push("profile", "openid");
this.clientSecret = clientSecret;
}
async createAuthorizationURL(codeVerifier) {
async createAuthorizationURL(codeVerifier, options) {
const scope = options?.scope ?? [];
scope.push("openid");
return await this.client.createAuthorizationURL({
state: generateState(),
codeVerifier,
scope: this.scope
scope
});

@@ -31,3 +30,3 @@ }

});
return {
const tokens = {
accessToken: result.access_token,

@@ -38,11 +37,4 @@ refreshToken: result.refresh_token,

};
return tokens;
}
async getUser(accessToken) {
const response = await fetch("https://api.line.me/v2/profile", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {

@@ -53,3 +45,3 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,

@@ -59,3 +51,4 @@ refreshToken: result.refresh_token,

};
return tokens;
}
}

@@ -5,9 +5,8 @@ import type { OAuth2Provider } from "../index.js";

private clientSecret;
private scope;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<LinkedInTokens>;
getUser(accessToken: string): Promise<LinkedInUser>;
refreshAccessToken(accessToken: string): Promise<LinkedInTokens>;
}

@@ -20,14 +19,1 @@ export interface LinkedInTokens {

}
export interface LinkedInUser {
sub: string;
name: string;
email: string;
email_verified: boolean;
given_name: string;
family_name: string;
locale: {
country: string;
language: string;
};
picture: string;
}

@@ -5,8 +5,6 @@ import { OAuth2Client } from "oslo/oauth2";

const tokenEndpoint = "https://www.linkedin.com/oauth/v2/accessToken";
const userinfoEndpoint = "https://api.linkedin.com/v2/userinfo";
export class LinkedIn {
client;
clientSecret;
scope;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {

@@ -16,9 +14,9 @@ redirectURI

this.clientSecret = clientSecret;
this.scope = options?.scope ?? [];
this.scope.push("openid", "profile");
}
async createAuthorizationURL(state) {
async createAuthorizationURL(state, options) {
const scope = options?.scope ?? [];
scope.push("openid");
return await this.client.createAuthorizationURL({
state,
scope: this.scope
scope
});

@@ -31,3 +29,3 @@ }

});
return {
const tokens = {
accessToken: result.access_token,

@@ -38,11 +36,17 @@ accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),

};
return tokens;
}
async getUser(accessToken) {
const response = await fetch(userinfoEndpoint, {
headers: {
Authorization: `Bearer ${accessToken}`
}
async refreshAccessToken(accessToken) {
const result = await this.client.refreshAccessToken(accessToken, {
authenticateWith: "request_body",
credentials: this.clientSecret
});
return await response.json();
const tokens = {
accessToken: result.access_token,
accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),
refreshToken: result.refresh_token,
refreshTokenExpiresAt: createDate(new TimeSpan(result.refresh_token_expires_in, "s"))
};
return tokens;
}
}
import type { OAuth2ProviderWithPKCE } from "../index.js";
export declare class MicrosoftEntraID implements OAuth2ProviderWithPKCE {
export declare class MicrosoftEntraId implements OAuth2ProviderWithPKCE {
private client;
private scope;
private clientSecret;
constructor(tenant: string, clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(tenant: string, clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(codeVerifier: string, options?: {
scope?: string[];
});
createAuthorizationURL(codeVerifier: string): Promise<URL>;
validateAuthorizationCode(code: string, codeVerifier: string): Promise<MicrosoftEntraIDTokens>;
getUser(accessToken: string): Promise<MicrosoftEntraIDUser>;
refreshAccessToken(refreshToken: string): Promise<MicrosoftEntraIDTokens>;
private parseIdToken;
}): Promise<URL>;
validateAuthorizationCode(code: string, codeVerifier: string): Promise<MicrosoftEntraIdTokens>;
refreshAccessToken(refreshToken: string): Promise<MicrosoftEntraIdTokens>;
}
export interface MicrosoftEntraIDIdTokenClaims {
sub: string;
iss: string;
aud: string;
idp: string;
iat: number;
nbf: number;
exp: number;
at_hash: string;
preferred_username: string;
email?: string;
name: string;
oid: string;
roles: string[];
tid: string;
uti: string;
ver: "1.0" | "2.0";
hasgroups?: true;
}
export interface MicrosoftEntraIDTokens {
export interface MicrosoftEntraIdTokens {
idToken: string;

@@ -39,11 +17,2 @@ accessToken: string;

refreshToken: string | null;
idTokenClaims: MicrosoftEntraIDIdTokenClaims;
}
export interface MicrosoftEntraIDUser {
sub: string;
name: string;
family_name: string;
given_name: string;
picture: string;
email?: string;
}
import { TimeSpan, createDate } from "oslo";
import { parseJWT } from "oslo/jwt";
import { OAuth2Client } from "oslo/oauth2";
export class MicrosoftEntraID {
export class MicrosoftEntraId {
client;
scope;
clientSecret;
constructor(tenant, clientId, clientSecret, redirectURI, options) {
constructor(tenant, clientId, clientSecret, redirectURI) {
const authorizeEndpoint = `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/authorize`;

@@ -14,10 +12,10 @@ const tokenEndpoint = `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`;

});
this.scope = options?.scope ?? [];
this.scope.push("openid", "profile");
this.clientSecret = clientSecret;
}
async createAuthorizationURL(codeVerifier) {
async createAuthorizationURL(codeVerifier, options) {
const scope = options?.scope ?? [];
scope.push("openid");
const url = await this.client.createAuthorizationURL({
scope: this.scope,
codeVerifier
codeVerifier,
scope
});

@@ -33,18 +31,10 @@ url.searchParams.set("nonce", "_");

});
return {
const tokens = {
accessToken: result.access_token,
refreshToken: result.refresh_token ?? null,
accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),
idToken: result.id_token,
idTokenClaims: this.parseIdToken(result.id_token)
idToken: result.id_token
};
return tokens;
}
async getUser(accessToken) {
const response = await fetch("https://graph.microsoft.com/oidc/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {

@@ -55,16 +45,10 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,
refreshToken: result.refresh_token ?? null,
accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),
idToken: result.id_token,
idTokenClaims: this.parseIdToken(result.id_token)
idToken: result.id_token
};
return tokens;
}
parseIdToken(idToken) {
const parsedIdToken = parseJWT(idToken);
if (!parsedIdToken)
throw new Error("Failed to parse ID token");
return parsedIdToken.payload;
}
}

@@ -11,14 +11,2 @@ import type { OAuth2Provider } from "../index.js";

accessToken: string;
user: NotionUser;
botId: string;
}
export interface NotionUser {
type: "person";
id: string;
name: string;
avatar_url: string;
person: NotionPersonUser;
}
export interface NotionPersonUser {
email: string;
}

@@ -24,8 +24,7 @@ import { OAuth2Client } from "oslo/oauth2";

});
return {
accessToken: result.access_token,
user: result.owner,
botId: result.bot_id
const tokens = {
accessToken: result.access_token
};
return tokens;
}
}
import type { OAuth2Provider } from "../index.js";
export declare class Reddit implements OAuth2Provider {
private client;
private scope;
private clientSecret;
private tokenDuration;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(state: string, options?: {
tokenDuration?: "permanent" | "temporary";
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<RedditTokens>;
getUser(accessToken: string): Promise<RedditUser>;
refreshAccessToken(refreshToken: string): Promise<RedditTokens>;

@@ -21,151 +18,1 @@ }

}
export interface RedditUser {
is_employee: boolean;
seen_layout_switch: boolean;
has_visited_new_profile: boolean;
pref_no_profanity: boolean;
has_external_account: boolean;
pref_geopopular: string;
seen_redesign_modal: boolean;
pref_show_trending: boolean;
subreddit: {
default_set: boolean;
user_is_contributor: boolean;
banner_img: string;
restrict_posting: boolean;
user_is_banned: boolean;
free_form_reports: boolean;
community_icon: string;
show_media: boolean;
icon_color: string;
user_is_muted: boolean;
display_name: string;
header_img: string;
title: string;
coins: number;
previous_names: string[];
over_18: boolean;
icon_size: [number, number];
primary_color: string;
icon_img: string;
description: string;
allowed_media_in_comments: any[];
submit_link_label: string;
header_size: any;
restrict_commenting: boolean;
subscribers: number;
submit_text_label: string;
is_default_icon: boolean;
link_flair_position: string;
display_name_prefixed: string;
key_color: string;
name: string;
is_default_banner: boolean;
url: string;
quarantine: boolean;
banner_size: [number, number];
user_is_moderator: boolean;
accept_followers: boolean;
public_description: string;
link_flair_enabled: boolean;
disable_contributor_requests: boolean;
subreddit_type: string;
user_is_subscriber: boolean;
};
pref_show_presence: boolean;
snoovatar_img: string;
snoovatar_size: [number, number];
gold_expiration: any;
has_gold_subscription: boolean;
is_sponsor: boolean;
num_friends: number;
features: {
mod_service_mute_writes: boolean;
promoted_trend_blanks: boolean;
show_amp_link: boolean;
chat: boolean;
is_email_permission_required: true;
mod_awards: boolean;
expensive_coins_package: boolean;
mweb_xpromo_revamp_v2: {
owner: string;
variant: string;
experiment_id: number;
};
awards_on_streams: boolean;
mweb_xpromo_modal_listing_click_daily_dismissible_ios: true;
chat_subreddit: boolean;
cookie_consent_banner: boolean;
modlog_copyright_removal: boolean;
do_not_track: boolean;
images_in_comments: boolean;
mod_service_mute_reads: boolean;
chat_user_settings: boolean;
use_pref_account_deployment: boolean;
mweb_xpromo_interstitial_comments_ios: boolean;
mweb_xpromo_modal_listing_click_daily_dismissible_android: boolean;
premium_subscriptions_table: boolean;
mweb_xpromo_interstitial_comments_android: true;
crowd_control_for_post: boolean;
mweb_nsfw_xpromo: {
owner: string;
variant: string;
experiment_id: number;
};
noreferrer_to_noopener: boolean;
chat_group_rollout: boolean;
resized_styles_images: boolean;
spez_modal: boolean;
mweb_sharing_clipboard: {
owner: string;
variant: string;
experiment_id: number;
};
};
can_edit_name: boolean;
verified: boolean;
pref_autoplay: boolean;
coins: number;
has_paypal_subscription: boolean;
has_subscribed_to_premium: boolean;
id: string;
has_stripe_subscription: boolean;
oauth_client_id: string;
can_create_subreddit: boolean;
over_18: boolean;
is_gold: boolean;
is_mod: boolean;
awarder_karma: number;
suspension_expiration_utc: any;
has_verified_email: boolean;
is_suspended: boolean;
pref_video_autoplay: boolean;
has_android_subscription: boolean;
in_redesign_beta: boolean;
icon_img: string;
pref_nightmode: boolean;
awardee_karma: number;
hide_from_robots: boolean;
password_set: boolean;
link_karma: number;
force_password_reset: boolean;
total_karma: number;
seen_give_award_tooltip: boolean;
inbox_count: number;
seen_premium_adblock_modal: boolean;
pref_top_karma_subreddits: boolean;
pref_show_snoovatar: boolean;
name: string;
pref_clickgadget: number;
created: number;
gold_creddits: number;
created_utc: number;
has_ios_subscription: boolean;
pref_show_twitter: boolean;
in_beta: boolean;
comment_karma: number;
accept_followers: boolean;
has_subscribed: boolean;
linked_identities: any[];
seen_subreddit_chat_ftux: boolean;
}

@@ -7,19 +7,15 @@ import { OAuth2Client } from "oslo/oauth2";

client;
scope;
clientSecret;
tokenDuration;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {
redirectURI
});
this.scope = options?.scope ?? [];
this.clientSecret = clientSecret;
this.tokenDuration = options?.tokenDuration ?? "temporary";
}
async createAuthorizationURL(state) {
async createAuthorizationURL(state, options) {
const url = await this.client.createAuthorizationURL({
state,
scope: this.scope
scope: options?.scope ?? []
});
url.searchParams.set("duration", this.tokenDuration);
url.searchParams.set("duration", options?.tokenDuration ?? "temporary");
return url;

@@ -31,3 +27,3 @@ }

});
return {
const tokens = {
accessToken: result.access_token,

@@ -37,11 +33,4 @@ accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),

};
return tokens;
}
async getUser(accessToken) {
const response = await fetch("https://oauth.reddit.com/api/v1/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {

@@ -51,3 +40,3 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,

@@ -57,3 +46,4 @@ accessTokenExpiresAt: createDate(new TimeSpan(result.expires_in, "s")),

};
return tokens;
}
}

@@ -1,12 +0,10 @@

import type { OAuth2ProviderWithPKCE } from "../index.js";
export declare class Slack implements OAuth2ProviderWithPKCE {
import type { OAuth2Provider } from "../index.js";
export declare class Slack implements OAuth2Provider {
private client;
private scope;
private clientSecret;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(codeVerifier: string): Promise<URL>;
validateAuthorizationCode(code: string, codeVerifier: string): Promise<SlackTokens>;
getUser(accessToken: string): Promise<SlackUser>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<SlackTokens>;
}

@@ -17,30 +15,1 @@ export interface SlackTokens {

}
export interface SlackUser {
sub: string;
"https://slack.com/user_id": string;
"https://slack.com/team_id": string;
email?: string;
email_verified: boolean;
date_email_verified: number;
name: string;
picture: string;
given_name: string;
family_name: string;
locale: string;
"https://slack.com/team_name": string;
"https://slack.com/team_domain": string;
"https://slack.com/user_image_24": string;
"https://slack.com/user_image_32": string;
"https://slack.com/user_image_48": string;
"https://slack.com/user_image_72": string;
"https://slack.com/user_image_192": string;
"https://slack.com/user_image_512": string;
"https://slack.com/team_image_34": string;
"https://slack.com/team_image_44": string;
"https://slack.com/team_image_68": string;
"https://slack.com/team_image_88": string;
"https://slack.com/team_image_102": string;
"https://slack.com/team_image_132": string;
"https://slack.com/team_image_230": string;
"https://slack.com/team_image_default": true;
}

@@ -6,37 +6,28 @@ import { OAuth2Client } from "oslo/oauth2";

client;
scope;
clientSecret;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {
redirectURI
});
this.scope = options?.scope ?? [];
this.scope.push("openid", "profile");
this.clientSecret = clientSecret;
}
async createAuthorizationURL(codeVerifier) {
async createAuthorizationURL(state, options) {
const scope = options?.scope ?? [];
scope.push("openid");
return await this.client.createAuthorizationURL({
codeVerifier,
scope: this.scope
state,
scope
});
}
async validateAuthorizationCode(code, codeVerifier) {
async validateAuthorizationCode(code) {
const result = await this.client.validateAuthorizationCode(code, {
authenticateWith: "request_body",
credentials: this.clientSecret,
codeVerifier
credentials: this.clientSecret
});
return {
const tokens = {
accessToken: result.access_token,
idToken: result.id_token
};
return tokens;
}
async getUser(accessToken) {
const response = await fetch("https://slack.com/api/openid.connect.userInfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
}

@@ -5,9 +5,7 @@ import type { OAuth2Provider } from "../index.js";

private clientSecret;
private scope;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<SpotifyTokens>;
getUser(accessToken: string): Promise<SpotifyUser>;
refreshAccessToken(refreshToken: string): Promise<SpotifyTokens>;

@@ -20,29 +18,1 @@ }

}
export interface SpotifyUser {
country?: string;
display_name: string | null;
email?: string;
explicit_content: {
filter_enabled?: boolean;
filter_locked?: boolean;
};
external_urls: {
spotify: string;
};
followers: {
href: string | null;
total: number;
};
href: string;
id: string;
images: [
{
url: string;
height: number | null;
width: number | null;
}
];
product?: string;
type: string;
uri: string;
}

@@ -8,4 +8,3 @@ import { TimeSpan, createDate } from "oslo";

clientSecret;
scope;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {

@@ -15,8 +14,7 @@ redirectURI

this.clientSecret = clientSecret;
this.scope = options?.scope ?? [];
}
async createAuthorizationURL(state) {
async createAuthorizationURL(state, options) {
return await this.client.createAuthorizationURL({
state,
scope: this.scope
scope: options?.scope ?? []
});

@@ -28,3 +26,3 @@ }

});
return {
const tokens = {
accessToken: result.access_token,

@@ -34,14 +32,7 @@ refreshToken: result.refresh_token,

};
return tokens;
}
async getUser(accessToken) {
const response = await fetch("https://api.spotify.com/v1/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {
const result = await this.client.refreshAccessToken(refreshToken);
return {
const tokens = {
accessToken: result.access_token,

@@ -51,3 +42,4 @@ refreshToken: result.refresh_token,

};
return tokens;
}
}
import type { OAuth2Provider } from "../index.js";
export declare class Twitch implements OAuth2Provider {
private client;
private scope;
private clientSecret;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(state: string, options?: {
scope?: string[];
});
createAuthorizationURL(state: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string): Promise<TwitchTokens>;
getUser(accessToken: string): Promise<TwitchUser>;
refreshAccessToken(refreshToken: string): Promise<TwitchTokens>;

@@ -19,14 +17,1 @@ }

}
export interface TwitchUser {
id: string;
login: string;
display_name: string;
type: "" | "admin" | "staff" | "global_mod";
broadcaster_type: "" | "affiliate" | "partner";
description: string;
profile_image_url: string;
offline_image_url: string;
view_count: number;
email?: string;
created_at: string;
}

@@ -7,15 +7,13 @@ import { TimeSpan, createDate } from "oslo";

client;
scope;
clientSecret;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {
redirectURI
});
this.scope = options?.scope ?? [];
this.clientSecret = clientSecret;
}
async createAuthorizationURL(state) {
async createAuthorizationURL(state, options) {
return await this.client.createAuthorizationURL({
state,
scope: this.scope
scope: options?.scope ?? []
});

@@ -28,3 +26,3 @@ }

});
return {
const tokens = {
accessToken: result.access_token,

@@ -34,11 +32,4 @@ refreshToken: result.refresh_token,

};
return tokens;
}
async getUser(accessToken) {
const response = await fetch("https://api.twitch.tv/helix/users", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {

@@ -49,3 +40,3 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,

@@ -55,3 +46,4 @@ refreshToken: result.refresh_token,

};
return tokens;
}
}
import type { OAuth2ProviderWithPKCE } from "../index.js";
export declare class Twitter implements OAuth2ProviderWithPKCE {
private client;
private scope;
private clientSecret;
constructor(clientId: string, clientSecret: string, redirectURI: string, options?: {
constructor(clientId: string, clientSecret: string, redirectURI: string);
createAuthorizationURL(codeVerifier: string, options?: {
scope?: string[];
});
createAuthorizationURL(codeVerifier: string): Promise<URL>;
}): Promise<URL>;
validateAuthorizationCode(code: string, codeVerifier: string): Promise<TwitterTokens>;
getUser(accessToken: string): Promise<TwitterUser>;
refreshAccessToken(refreshToken: string): Promise<TwitterTokens>;

@@ -18,6 +16,1 @@ }

}
export interface TwitterUser {
id: string;
name: string;
username: string;
}

@@ -6,17 +6,14 @@ import { OAuth2Client, generateState } from "oslo/oauth2";

client;
scope;
clientSecret;
constructor(clientId, clientSecret, redirectURI, options) {
constructor(clientId, clientSecret, redirectURI) {
this.client = new OAuth2Client(clientId, authorizeEndpoint, tokenEndpoint, {
redirectURI
});
this.scope = options?.scope ?? [];
this.scope.push("users.read");
this.clientSecret = clientSecret;
}
async createAuthorizationURL(codeVerifier) {
async createAuthorizationURL(codeVerifier, options) {
return await this.client.createAuthorizationURL({
state: generateState(),
scope: this.scope,
codeVerifier
codeVerifier,
scope: options?.scope ?? []
});

@@ -29,15 +26,8 @@ }

});
return {
const tokens = {
accessToken: result.access_token,
refreshToken: result.refresh_token ?? null
};
return tokens;
}
async getUser(accessToken) {
const response = await fetch("https://api.twitter.com/2/users/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
return await response.json();
}
async refreshAccessToken(refreshToken) {

@@ -48,7 +38,8 @@ const result = await this.client.refreshAccessToken(refreshToken, {

});
return {
const tokens = {
accessToken: result.access_token,
refreshToken: result.refresh_token ?? null
};
return tokens;
}
}
{
"name": "arctic",
"type": "module",
"version": "0.7.1",
"version": "0.8.0",
"description": "OAuth 2.0 with built-in providers",

@@ -6,0 +6,0 @@ "main": "dist/index.js",

@@ -1,19 +0,31 @@

# `arctic`
# Arctic
Library for handling OAuth 2.0 with built-in providers. Light weight, fully-typed, runtime-agnostic. Built using [`oslo`](http://github.com/pilcrowonpaper/oslo). For a more flexible OAuth 2.0 client, see [`oslo/oauth2`](http://github.com/pilcrowonpaper/oslo).
Arctic is an OAuth 2.0 library for JavaScript/TypeScript that supports numerous providers. It's light weight, fully-typed, and runtime-agnostic.
```ts
import { GitHub, generateState } from "arctic";
const github = new GitHub(clientId, clientSecret);
const state = generateState();
const authorizationURL = await github.createAuthorizationURL(state, {
scope: ["user:email"]
});
const tokens = await github.validateAuthorizationCode(code);
```
npm install arctic
```
## Providers
[Read the documentation](./docs/main.md)
### OAuth 2.0
> For a more flexible OAuth 2.0 client, see [`oslo/oauth2`](http://github.com/pilcrowonpaper/oslo).
See [OAuth 2.0 providers](#oauth-20-providers) for instructions.
## Supported providers
- Apple
- Atlassian
- Auth0
- Bitbucket
- Box
- Discord
- Dropbox
- Facebook

@@ -23,4 +35,8 @@ - Figma

- GitLab
- Google
- Kakao
- Keycloak
- Line
- LinkedIn
- Microsoft Entra ID
- Notion

@@ -30,197 +46,3 @@ - Reddit

- Twitch
### OAuth 2.0 with PKCE
See [OAuth 2.0 providers with PKCE](#oauth-20-providers-with-pkce) for instructions.
- Google
- Keycloak
- Line
- Microsoft Entra ID
- Twitter
## OAuth 2.0 providers
Most providers require the `client_id` and `client_secret`. You may also optionally pass `scope`. For OIDC clients, `openid` and `profile` scope are always included.
```ts
import { GitHub } from "arctic";
const github = new GitHub(clientId, clientSecret, {
scope: ["user:email"] // etc
});
```
Some providers also require the redirect URI.
```ts
import { Google } from "arctic";
const redirectURI = "http://localhost:3000/login/google/callback";
const google = new Google(clientId, clientSecret, redirectURI);
```
### Create authorization URL
Generate state using `generateState()` and store it as a cookie. Use it to create an authorization URL with `createAuthorizationURL()` and redirect the user to it.
```ts
import { generateState } from "arctic";
const state = generateState();
const url = await github.createAuthorizationURL(state);
// store state as cookie
setCookie("state", state, {
secure: true, // set to false in localhost
path: "/",
httpOnly: true,
maxAge: 60 * 10 // 10 min
});
return redirect(url);
```
### Validate authorization code
Compare the state, and use `validateAuthorizationCode()` to validate the authorization code. This returns an object with an access token, and a refresh token if requested. If the code is invalid, it will throw an `AccessTokenRequestError`.
```ts
import { OAuth2RequestError } from "arctic";
const code = request.url.searchParams.get("code");
const state = request.url.searchParams.get("state");
const storedState = getCookie("state");
if (!code || !storedState || state !== storedState) {
// 400
throw new Error("Invalid request");
}
try {
const tokens = await github.validateAuthorizationCode(code);
} catch (e) {
if (e instanceof OAuth2RequestError) {
const { message, description, request } = e;
}
// unknown error
}
```
### Other
See also:
- [Get the current user](#get-the-current-user)
- [Refresh access tokens](#refresh-access-tokens)
## OAuth 2.0 providers with PKCE
Most providers require the `client_id` and `client_secret`. You may also optionally pass `scope`. For OIDC clients, `openid` and `profile` scope are always included.
```ts
import { GitHub } from "arctic";
const github = new GitHub(clientId, clientSecret, {
scope: ["user:email"] // etc
});
```
Some providers also require the redirect URI.
```ts
import { Google } from "arctic";
const redirectURI = "http://localhost:3000/login/google/callback";
const google = new Google(clientId, clientSecret, redirectURI);
```
### Create authorization URL
When using the PKCE flow, `state` is not necessary. Generate a code verifier using `generateCodeVerifier()`, and store it as a cookie. Use them to create an authorization URL with `createAuthorizationURL()` and redirect the user to it.
```ts
import { generateState, generateCodeVerifier } from "arctic";
const codeVerifier = generateCodeVerifier();
const url = await github.createAuthorizationURL(state, codeVerifier);
// store code verifier as cookie
setCookie("code_verifier", state, {
secure: true, // set to false in localhost
path: "/",
httpOnly: true,
maxAge: 60 * 10 // 10 min
});
return redirect(url);
```
### Validate authorization code
Use `validateAuthorizationCode()` to validate the authorization code with the code verifier. This returns an object with an access token, and a refresh token if requested. If the code is invalid, it will throw an `AccessTokenRequestError`.
```ts
import { OAuth2RequestError } from "arctic";
const code = request.url.searchParams.get("code");
const codeVerifier = request.url.searchParams.get("code_verifier");
try {
const tokens = await github.validateAuthorizationCode(code, codeVerifier);
} catch (e) {
if (e instanceof OAuth2RequestError) {
// see https://oslo.js.org/reference/oauth2/OAuth2RequestError/
const { request, message, description } = e;
}
// unknown error
}
```
### Other
See also:
- [Get the current user](#get-the-current-user)
- [Refresh access tokens](#refresh-access-tokens)
## Other
### Get the current user
Some providers expose `getUser()` to get the current user from an access token. This will throw an `RequestError` if the access token is invalid.
```ts
import { RequestError } from "arctic";
try {
const user = await github.getUser(tokens.accessToken);
} catch (e) {
if (e instanceof RequestError) {
// get fetch Request and Response
const { request, response } = e;
}
// unknown error
}
```
### Refresh access tokens
Some providers expose `refreshAccessToken()` to get a new access token from a refresh token. This will throw an `OAuth2RequestError` if the refresh token is invalid.
```ts
import { OAuth2RequestError } from "arctic";
try {
const tokens = await google.refreshAccessToken(refreshToken);
} catch (e) {
if (e instanceof OAuth2RequestError) {
// see https://oslo.js.org/reference/oauth2/OAuth2RequestError/
const { request, message, description } = e;
}
// unknown error
}
```
- Yahoo
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc