diff --git a/src/providers/github.ts b/src/providers/github.ts new file mode 100644 index 0000000..274d64c --- /dev/null +++ b/src/providers/github.ts @@ -0,0 +1,50 @@ +import { OAuth2Provider, OAuth2ProviderConfig } from "./oauth2"; + +export interface GitHubProfile { + id: number; + login: string; + avatar_url: string; + url: string; + name: string; + // complete with more info +} + +export interface GitHubTokens { + access_token: string; + token_type: string; + expires_in: number; +} + +type GitHubOAuth2ProviderConfig = OAuth2ProviderConfig; + +const defaultConfig: Partial = { + id: "github", + scope: "user", + accessTokenUrl: "https://github.com/login/oauth/access_token", + authorizationUrl: "https://github.com/login/oauth/authorize", + profileUrl: "https://api.github.com/user", + headers: { + Accept: "application/json", + }, +}; + +export class GitHubOAuth2Provider extends OAuth2Provider< + GitHubProfile, + GitHubTokens, + GitHubOAuth2ProviderConfig +> { + constructor(config: GitHubOAuth2ProviderConfig) { + super({ + ...defaultConfig, + ...config, + }); + } + + async getUserProfile(tokens: GitHubTokens): Promise { + const tokenType = "token"; // 🤷‍♂️ token type returned is "bearer" but GitHub uses "token" keyword + const res = await fetch(this.config.profileUrl!, { + headers: { Authorization: `${tokenType} ${tokens.access_token}` }, + }); + return await res.json(); + } +} diff --git a/src/providers/index.ts b/src/providers/index.ts index 84418eb..8e422f6 100644 --- a/src/providers/index.ts +++ b/src/providers/index.ts @@ -11,3 +11,5 @@ export type { ProfileCallback } from "./oauth2.base"; export { OAuth2Provider } from "./oauth2"; export { RedditOAuth2Provider } from "./reddit"; export type { RedditProfile, RedditTokens } from "./reddit"; +export { GitHubOAuth2Provider } from "./github"; +export type { GitHubProfile, GitHubTokens } from "./github"; \ No newline at end of file