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

@react-oauth/github

v0.1.0

Published

A modern, fully-typed React hook for GitHub OAuth authentication πŸš€

Readme

A modern, production-grade React hook for GitHub OAuth authentication


Features

  • βœ… Production-Ready - Battle-tested and optimized for real-world applications
  • βœ… Fully Typed - Complete TypeScript support with exported types
  • βœ… Zero Dependencies - No runtime dependencies (only React peer deps)
  • βœ… Flexible API - Custom hook for complete UI control
  • βœ… Well Documented - Extensive documentation and examples

Quick Start

Installation

npm install @react-oauth/github
# or
yarn add @react-oauth/github
# or
pnpm add @react-oauth/github

Basic Usage

import { useGitHubLogin } from '@react-oauth/github';

function CustomLoginButton() {
  const { initiateGitHubLogin, isLoading } = useGitHubLogin({
    clientId: 'your-github-client-id',
    redirectUri: 'http://localhost:3000/callback',
    onSuccess: response => {
      console.log('Authorization code:', response.code);
    },
    onError: error => {
      console.error('Authentication failed:', error);
    },
  });

  return (
    <button onClick={initiateGitHubLogin} disabled={isLoading}>
      {isLoading ? 'Loading...' : 'Sign in with GitHub'}
    </button>
  );
}

API Reference

useGitHubLogin Hook

A custom React hook that provides GitHub OAuth functionality. Use this when you want complete control over your UI. All options, including callbacks, are passed in a single object.

Parameters

useGitHubLogin(options: UseGitHubLoginOptions): UseGitHubLoginReturn

Options

| Option | Type | Required | Default | Description | | -------------- | ----------------------------------- | -------- | -------------- | -------------------------------------------------------------------- | | clientId | string | βœ… | - | Your GitHub OAuth App Client ID | | onSuccess | (response: OAuthResponse) => void | βœ… | - | Callback called when authentication succeeds | | onError | (error: Error) => void | βœ… | - | Callback called when authentication fails | | redirectUri | string | ❌ | '' | Registered redirect URI for your OAuth App | | scope | string | ❌ | 'user:email' | OAuth scopes to request (comma-separated) | | popupOptions | PopupWindowOptions | ❌ | - | Options for configuring the popup window | | state | string | ❌ | Auto-generated | State parameter for CSRF protection (auto-generated if not provided) | | allowSignup | boolean | ❌ | true | Whether to allow signup during authentication | | onRequest | () => void | ❌ | - | Optional callback called when OAuth flow is initiated |

Return Value

{
  initiateGitHubLogin: () => void;  // Function to initiate OAuth flow
  isLoading: boolean;                // Loading state during authentication
}

Types

interface OAuthResponse {
  code: string;
  state?: string;
  error?: string;
  error_description?: string;
}

interface PopupWindowOptions {
  height?: number;
  width?: number;
  left?: number;
  top?: number;
}

interface UseGitHubLoginOptions {
  clientId: string;
  redirectUri?: string;
  scope?: string;
  popupOptions?: PopupWindowOptions;
  state?: string; // Auto-generated if not provided
  allowSignup?: boolean;
  onSuccess: (response: OAuthResponse) => void;
  onError: (error: Error) => void;
  onRequest?: () => void;
}

interface UseGitHubLoginReturn {
  initiateGitHubLogin: () => void;
  isLoading: boolean;
}

Common Scopes

  • user:email - Read user email addresses (default)
  • repo - Full control of private repositories
  • read:org - Read org and team membership
  • gist - Create gists
  • notifications - Access notifications

See GitHub OAuth Scopes for the full list.

Error Handling

The hook provides comprehensive error handling with standardized error codes. All OAuth-related errors are Error objects with a code property containing specific error codes:

Error Codes

| Code | Description | | ------- | ----------------------------------------------------------------------------------------- | | OA001 | The Popup Closed - User closed the popup window before completing authentication | | OA002 | Popup Blocked By Browser - Browser blocked the popup window (user needs to enable popups) | | OA003 | State Mismatch - State parameter mismatch detected (possible CSRF attack) | | OA004 | Missing Code - Authorization code not found in OAuth response |

Usage

import {
  useGitHubLogin,
  OAuthError,
  OAuthErrorCode,
} from '@react-oauth/github';

function LoginButton() {
  const { initiateGitHubLogin, isLoading } = useGitHubLogin({
    clientId: 'your-client-id',
    onSuccess: handleSuccess,
    onError: error => {
      if (OAuthError.isOAuthError(error)) {
        switch (error.code) {
          case OAuthErrorCode.POPUP_CLOSED:
            console.log('User closed the popup');
            // Handle popup closed
            break;
          case OAuthErrorCode.POPUP_BLOCKED:
            console.log('Popup blocked by browser');
            // Prompt user to enable popups
            break;
          case OAuthErrorCode.STATE_MISMATCH:
            console.log('State mismatch - possible CSRF attack');
            // Handle security issue
            break;
          case OAuthErrorCode.MISSING_CODE:
            console.log('Authorization code not found in response');
            // Handle missing code
            break;
          default:
            console.log('Other OAuth error:', error.message);
        }
      } else {
        // Handle other errors
        console.error('Unexpected error:', error);
      }
    },
  });

  return (
    <button onClick={initiateGitHubLogin} disabled={isLoading}>
      {isLoading ? 'Loading...' : 'Sign in with GitHub'}
    </button>
  );
}

Error Object Structure

type OAuthError = Error & {
  code: OAuthErrorCode; // Error code (e.g., "OA001")
};

CSRF Protection

The package automatically generates a state parameter for CSRF protection if you don't provide one. The state is verified when the OAuth callback returns. If you provide your own state, make sure to verify it matches in your onSuccess callback:

const { initiateGitHubLogin } = useGitHubLogin({
  clientId: 'your-client-id',
  state: 'your-custom-state', // Optional - auto-generated if not provided
  onSuccess: response => {
    // State is automatically verified by the package
    // But you can also verify it manually if needed
    if (response.state === 'your-custom-state') {
      // Proceed with authentication
    }
  },
  onError: error => console.error(error),
});

How It Works

This package implements the OAuth 2.0 Authorization Code Flow with a popup window. The flow ensures secure authentication by keeping sensitive credentials (like the Client Secret) on your backend.

sequenceDiagram
    participant User
    participant Frontend as Frontend<br/>(React App)
    participant GitHub as GitHub<br/>OAuth Server
    participant Backend as Your Backend<br/>Server

    User->>Frontend: Clicks "Sign in with GitHub"
    Frontend->>Frontend: Opens popup window
    Frontend->>GitHub: Redirects to OAuth authorize endpoint<br/>(with client_id, redirect_uri, state, scope)
    GitHub->>User: Shows login/authorization page
    User->>GitHub: Authenticates & authorizes app
    GitHub->>Frontend: Redirects popup to redirect_uri<br/>(with authorization code & state)
    Frontend->>Frontend: Extracts authorization code<br/>(via polling mechanism)
    Frontend->>Backend: Sends authorization code<br/>(POST /api/github/callback)
    Backend->>GitHub: Exchanges code for access token<br/>(POST /login/oauth/access_token<br/>with client_id, client_secret, code)
    GitHub->>Backend: Returns access token
    Backend->>GitHub: Fetches user data<br/>(GET /user with access token)
    GitHub->>Backend: Returns user profile data
    Backend->>Frontend: Responds with user data
    Frontend->>User: User is authenticated

Key Points

  • Authorization Code: The temporary code returned by GitHub is called an "authorization code" (not an access token)
  • Security: The Client Secret never leaves your backend - the code exchange happens server-side
  • Popup Flow: Uses a popup window with polling to detect when GitHub redirects back
  • State Parameter: Automatically generated for CSRF protection

Setup

1. Create a GitHub OAuth App

  1. Go to GitHub Developer Settings
  2. Click "New OAuth App"
  3. Fill in the application details:
    • Application name: Your app name
    • Homepage URL: Your app URL
    • Authorization callback URL: Your redirect URI (e.g., http://localhost:3000/callback)
  4. Click "Register application"
  5. Copy the Client ID (you'll need this for the hook)

2. Exchange Authorization Code for Access Token

The hook returns an authorization code that you need to exchange for an access token on your backend. Never exchange the code on the client side - this requires your Client Secret.

Backend Example (Node.js/Express):

app.post('/api/github/callback', async (req, res) => {
  const { code } = req.body;

  const response = await fetch('https://github.com/login/oauth/access_token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json',
    },
    body: JSON.stringify({
      client_id: process.env.GITHUB_CLIENT_ID,
      client_secret: process.env.GITHUB_CLIENT_SECRET,
      code,
    }),
  });

  const data = await response.json();
  const { access_token } = data;

  // Use access_token to fetch user data
  const userResponse = await fetch('https://api.github.com/user', {
    headers: {
      Authorization: `token ${access_token}`,
    },
  });

  const user = await userResponse.json();
  // Handle user authentication...
});

License

MIT