npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@molecule/api-oauth-github

v1.2.1

Published

GitHub OAuth provider for molecule.dev.

Readme

@molecule/api-oauth-github

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

GitHub OAuth provider for molecule.dev.

Quick Start

// npm install @molecule/api-oauth-github --workspace=api
// Env: OAUTH_GITHUB_CLIENT_ID, OAUTH_GITHUB_CLIENT_SECRET (server-only).
import { bond } from '@molecule/api-bond'
import { getAuthorizeUrl, serverName, verify } from '@molecule/api-oauth-github'

// api/src/bonds/oauth-github.ts, called from setupBonds() — the `oauth`
// category is NAMED: providers coexist, and the bond name IS the
// serverName ('github').
bond('oauth', serverName, { serverName, verify, getAuthorizeUrl })

// Redirect: register the app origin + each OAuth-starting page path
// (e.g. {origin} and {origin}/login) as the OAuth App's "Authorization
// callback URL"; the login button just links to GET /users/oauth/github.

Type

provider

Installation

npm install @molecule/api-oauth-github @molecule/api-bond @molecule/api-http @molecule/api-oauth @molecule/api-secrets

API

Interfaces

OAuthAuthorizeUrlParams

Parameters for building a provider authorization (initiation) URL — the URL the user's browser is redirected to so the provider can authenticate them and send back an authorization code.

interface OAuthAuthorizeUrlParams {
  /**
   * Absolute URI the provider should redirect the user back to after
   * authorization (the app origin, optionally with a path). When omitted,
   * the builder leaves `redirect_uri` off the URL so the provider falls
   * back to its registered callback URL.
   */
  redirectUri?: string
  /**
   * The CSRF `state` parameter bound to the initiating session (stored in
   * an httpOnly cookie by the initiation endpoint and validated by the
   * login handler on callback).
   */
  state: string
  /**
   * PKCE code challenge derived (S256) from the per-session code verifier.
   * Omit only for providers that do not support PKCE.
   */
  codeChallenge?: string
  /**
   * PKCE challenge method. Always prefer `'S256'`; `'plain'` exists only
   * for providers that cannot hash.
   */
  codeChallengeMethod?: 'S256' | 'plain'
}

OAuthUserProps

The properties returned when verifying an OAuth code.

interface OAuthUserProps {
  /**
   * An alphanumeric username derived from the OAuth provider.
   *
   * Format: `{provider_username}@{provider_name}`
   */
  username: string
  /**
   * The user's display name from the OAuth provider.
   */
  name?: string
  /**
   * The user's short biography / description from the OAuth provider
   * (e.g. GitHub's `bio`, GitLab's `bio`, X's `description`). Omitted when
   * the provider exposes no such field.
   */
  bio?: string
  /**
   * URL of the user's profile image from the OAuth provider (e.g. Google's
   * `picture`, GitHub/GitLab's `avatar_url`, X's `profile_image_url`).
   * Omitted when the provider exposes none (Apple never does; Microsoft
   * Graph only serves photos as a binary endpoint behind an extra scope).
   */
  avatar?: string
  /**
   * The user's email address from the OAuth provider.
   */
  email?: string
  /**
   * Whether the OAuth provider has affirmatively verified that the user
   * controls this `email` mailbox.
   *
   * `true` MUST mean the provider proved mailbox ownership (e.g. Google's
   * `email_verified`, Apple's `email_verified` ID-token claim). When the
   * provider exposes no trustworthy verification signal in the profile data
   * the verifier fetched, this MUST be `false`/`undefined` (never optimistically
   * `true`) — consumers treat only an explicit `true` as verified.
   *
   * Consumers (e.g. the user resource's `logInOAuth` handler) use this to
   * decide whether a provider-supplied email may be trusted over an existing,
   * unverified local account — preventing an unverified squatter from blocking
   * the verified mailbox owner.
   */
  emailVerified?: boolean
  /**
   * The OAuth server identifier (e.g., 'github', 'google', 'twitter').
   */
  oauthServer: string
  /**
   * Unique identifier for the user from the OAuth provider.
   */
  oauthId: string
  /**
   * Raw user data from the OAuth provider.
   */
  oauthData: Record<string, unknown>
}

Types

OAuthAuthorizeUrlBuilder

Builds the provider's authorization URL for OAuth initiation (GET /users/oauth/:provider → 302 to this URL). Implementations embed their own client id, scopes, and authorize endpoint so no consumer ever hardcodes provider knowledge.

type OAuthAuthorizeUrlBuilder = (params: OAuthAuthorizeUrlParams) => string | null

OAuthVerifier

Exchanges an OAuth authorization code for user profile information.

Implementations call the provider's token and user-info endpoints, then return normalized OAuthUserProps for account creation or login.

Returning null means the provider AFFIRMATIVELY rejected the code (e.g. GitHub's bad_verification_code, an expired/forged code) — the consumer (logInOAuth) surfaces that as a clean 403 "verification failed". A thrown error means an infrastructure failure (network, provider outage) and surfaces as a 500. Implementations MUST NOT throw for a rejected code — that would misreport a client mistake (or an attack) as a server fault.

type OAuthVerifier = (
  code: string,
  codeVerifier?: string,
  redirectUri?: string,
) => Promise<OAuthUserProps | null>

Functions

getAuthorizeUrl(params)

Builds the GitHub authorization URL for OAuth initiation (GET /users/oauth/:provider 302s the browser here). Embeds this bond's client id and scopes (read:user user:email) plus the caller's CSRF state and PKCE S256 challenge, so no consumer hardcodes GitHub knowledge. The authorize endpoint defaults to GitHub.com but can be overridden via OAUTH_GITHUB_AUTHORIZE_URL for GitHub Enterprise.

function getAuthorizeUrl({
  redirectUri,
  state,
  codeChallenge,
  codeChallengeMethod,
}: OAuthAuthorizeUrlParams): string | null
  • params — State, PKCE challenge, and optional redirect URI.

Returns: The GitHub authorize URL, or null when OAUTH_GITHUB_CLIENT_ID is unset.

verify(code, codeVerifier, redirectUri)

Exchanges a GitHub OAuth authorization code for an access token, then fetches the authenticated user's profile from the GitHub API.

The token and user-info URLs default to GitHub.com, but can be overridden via OAUTH_GITHUB_TOKEN_URL and OAUTH_GITHUB_USER_URL for GitHub Enterprise deployments or E2E mock servers.

function verify(
  code: string,
  codeVerifier?: string,
  redirectUri?: string,
): Promise<{
  username: string
  name: string | undefined
  bio: string | undefined
  avatar: string | undefined
  email: string | undefined
  emailVerified: boolean
  oauthServer: 'github'
  oauthId: string
  oauthData: Record<string, unknown>
} | null>
  • code — The authorization code from the OAuth callback.
  • codeVerifier — The PKCE code verifier (if PKCE was used in the auth request).
  • redirectUri — The redirect URI used in the authorization request. Included in the token exchange (falling back to APP_ORIGIN) — GitHub.com is lenient about a mismatch, but a redirect_uri-enforcing GitHub Enterprise instance or strict proxy would otherwise reject the exchange with an error that looks unrelated to the missing parameter.

Returns: An OAuthUserInfo with the user's GitHub username, email, and OAuth ID.

Constants

oauthGithubSecretDefinitions

Secret definitions required by the GitHub OAuth bond.

const oauthGithubSecretDefinitions: SecretDefinition[]

serverName

The OAuth server identifier for GitHub.

const serverName: 'github'

Core Interface

Implements @molecule/api-oauth interface.

Bond Wiring

Setup function to register this provider with the bond system:

import { bond } from '@molecule/api-bond'
import { serverName, verify, getAuthorizeUrl } from '@molecule/api-oauth-github'

export function setupOauthGithub(): void {
  bond('oauth', serverName, { serverName, verify, getAuthorizeUrl })
}

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-bond ^1.0.1
  • @molecule/api-http ^1.0.1
  • @molecule/api-oauth ^1.0.1
  • @molecule/api-secrets ^1.0.1

Environment Variables

  • OAUTH_GITHUB_CLIENT_ID (required) — GitHub OAuth client ID
    • Setup: GitHub → Settings → Developer settings → OAuth Apps → New OAuth App; set the Authorization callback URL to your APP ORIGIN plus each page path that starts OAuth (e.g. {appUrl} and {appUrl}/login) — the API sends redirect_uri = APP_ORIGIN + the initiating page path.
    • Get it here: https://github.com/settings/developers
    • Example: Iv1.abc123...
  • OAUTH_GITHUB_CLIENT_SECRET (required) — GitHub OAuth client secret

Runtime Dependencies

  • @molecule/api-bond

  • @molecule/api-http

  • @molecule/api-oauth

  • @molecule/api-secrets

  • The token exchange (verify's call to GitHub's token endpoint) is application/x-www-form-urlencoded, per RFC 6749 §4.1.3 — matching every other molecule.dev OAuth bond (google, gitlab, twitter, apple, microsoft). GitHub's endpoint also accepts JSON, but form-encoding is the spec-compliant, universally-supported choice.

  • verify accepts a third redirectUri argument (falling back to APP_ORIGIN, same as the other bonds) and includes it in the token exchange. GitHub.com itself is lenient about a missing/mismatched redirect_uri, but a redirect_uri-enforcing GitHub Enterprise instance or strict proxy would otherwise reject the exchange with an error that looks unrelated to the missing parameter.

E2E Tests

Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:

  • [ ] Clicking the app's "Sign in with {provider}" button (Google, GitHub, …) redirects to the provider's authorize URL carrying the correct client_id, the app's requested scopes, AND the app's registered redirect_uri — inspect the actual outbound URL (the 302 Location, or the address the popup/tab navigates to) and confirm each value; a missing or wrong one is the bug.
  • [ ] The callback route exchanges the returned code SERVER-SIDE for a token, fetches the profile, and creates-or-links the app user + establishes a session — after the round-trip the app shows that user logged in. CAVEAT: the provider's own consent screen runs on ITS domain and CANNOT be driven in the sandbox, so verify the two boundaries you DO own — the authorize URL going out (above) and the callback coming back — not the provider's page. Complete the round-trip with a test/stub provider bond if one is wired; otherwise assert the callback handler's own behavior (state check → code exchange → user create-or-link → session). Never mock the flow or edit production code to bypass the provider.
  • [ ] A returning OAuth user logs into the SAME account — sign in twice and confirm one user row linked by provider id (oauthServer + oauthId), not a fresh duplicate created each time.
  • [ ] SECURITY — the state parameter is generated on initiation and verified on callback (CSRF protection): a mismatched or absent state is rejected (403); the redirect_uri is validated against an allowlist so an attacker cannot redirect the code elsewhere; and the client secret + tokens stay server-side — grep the browser bundle and network tab to confirm the secret never reaches the client (only the authorize URL and returned code cross the boundary).