Skip to content

The OAuthify library provides a seamless integration for adding OAuth-based login functionality into your React application. This package comes with pre-built headless components for Google and GitHub login buttons, making the OAuth flow implementation straightforward and efficient.

Notifications You must be signed in to change notification settings

shekhardtu/oauthify

Repository files navigation

OAuthify πŸ”

A modern, type-safe, and lightweight OAuth authentication library for React applications. Supports major OAuth providers with full TypeScript support and zero dependencies (except React).

npm version Bundle Size TypeScript License: ISC

✨ Features

  • πŸš€ Major OAuth Providers - Pre-built components for Google, GitHub, Microsoft, Facebook, LinkedIn, Apple + support for Discord, Twitter, Spotify, Slack and any OAuth 2.0 provider
  • πŸ“¦ Tiny Bundle - Only 12KB minified (45% smaller than v0.0.32)
  • πŸ”’ Secure - PKCE support, state validation, origin checking
  • πŸ’ͺ Type-Safe - Full TypeScript support with provider-specific types
  • 🎨 Customizable - Use pre-built buttons or create your own
  • ⚑ Zero Dependencies - Only requires React as peer dependency
  • πŸͺŸ Smart Window Management - Reuses existing auth windows
  • 🧹 Memory Safe - Automatic cleanup, no memory leaks

πŸ“¦ Installation

npm install oauthify
# or
yarn add oauthify
# or
pnpm add oauthify

πŸš€ Quick Start

1. Setup the Provider

Wrap your app with OAuthifyProvider:

import { OAuthifyProvider } from 'oauthify';

function App() {
  return (
    <OAuthifyProvider>
      {/* Your app components */}
    </OAuthifyProvider>
  );
}

2. Add the Redirect Handler

Create a redirect page at /auth/callback (or your chosen redirect path):

// pages/auth/callback.tsx or app/auth/callback/page.tsx
import { OAuthifyRedirect } from 'oauthify';

export default function AuthCallback() {
  return <OAuthifyRedirect />;
}

3. Use Login Buttons

import { GoogleLoginButton, GitHubLoginButton } from 'oauthify';

function LoginPage() {
  const handleSuccess = (response) => {
    console.log('OAuth Code:', response.code);
    // Send code to your backend to exchange for tokens
  };

  const handleError = (error) => {
    console.error('OAuth Error:', error);
  };

  return (
    <div>
      <GoogleLoginButton
        clientId="YOUR_GOOGLE_CLIENT_ID"
        redirectUri="http://localhost:3000/auth/callback"
        onSuccess={handleSuccess}
        onFailure={handleError}
      >
        Sign in with Google
      </GoogleLoginButton>

      <GitHubLoginButton
        clientId="YOUR_GITHUB_CLIENT_ID"
        redirectUri="http://localhost:3000/auth/callback"
        onSuccess={handleSuccess}
        onFailure={handleError}
      />
    </div>
  );
}

πŸ”‘ OAuth Provider Setup

Getting OAuth Credentials

Each provider requires you to register your application and obtain credentials:

Provider Setup Documentation Required Credentials
Google Google Cloud Console Client ID, Client Secret
GitHub GitHub OAuth Apps Client ID, Client Secret
Microsoft Azure App Registration Application ID, Client Secret, Tenant ID
Facebook Facebook Developers App ID, App Secret
LinkedIn LinkedIn Developers Client ID, Client Secret
Apple Apple Developer Service ID, Private Key, Team ID
Discord Discord Developers Client ID, Client Secret
Twitter Twitter Developer Portal Client ID, Client Secret
Spotify Spotify Dashboard Client ID, Client Secret
Slack Slack API Apps Client ID, Client Secret

Important Setup Notes

  1. Redirect URI: Must match exactly in your app configuration and provider settings
  2. HTTPS Required: Most providers require HTTPS in production (localhost is usually exempt)
  3. Scopes: Each provider has different available scopes - check their documentation

πŸ“– API Reference

Components

<GoogleLoginButton />

interface GoogleLoginButtonProps {
  clientId: string;
  redirectUri: string;
  onSuccess?: (response: OAuthResponse) => void;
  onFailure?: (error: OAuthError) => void;
  scope?: string; // Default: 'openid profile email'
  prompt?: 'none' | 'consent' | 'select_account';
  accessType?: 'online' | 'offline';
  children?: ReactNode;
  className?: string;
  disabled?: boolean;
}

<GitHubLoginButton />

interface GitHubLoginButtonProps {
  clientId: string;
  redirectUri: string;
  onSuccess?: (response: OAuthResponse) => void;
  onFailure?: (error: OAuthError) => void;
  scope?: string; // Default: 'user:email'
  allowSignup?: boolean;
  children?: ReactNode;
  className?: string;
  disabled?: boolean;
}

<MicrosoftLoginButton />

interface MicrosoftLoginButtonProps {
  clientId: string;
  redirectUri: string;
  tenant?: string; // Default: 'common'
  onSuccess?: (response: OAuthResponse) => void;
  onFailure?: (error: OAuthError) => void;
  responseMode?: 'query' | 'fragment';
  prompt?: 'login' | 'none' | 'consent' | 'select_account';
  loginHint?: string;
  domainHint?: string;
  children?: ReactNode;
  className?: string;
  disabled?: boolean;
}

<FacebookLoginButton />, <LinkedInLoginButton />, <AppleLoginButton />

Similar interfaces with provider-specific options. See TypeScript definitions for full details.

Hooks

useOAuthify()

Access the OAuth context and state:

const {
  state,           // { loading, success, error, activeProvider }
  setOnSuccess,    // Handle success globally
  setOnFailure,    // Handle failure globally
  setLoading,      // Set loading state
  clearState,      // Clear all state
  clearError       // Clear error state
} = useOAuthify();

useOAuthListener(options)

Listen for OAuth responses:

useOAuthListener({
  provider: 'google',  // Optional: filter by provider
  onSuccess: (result) => console.log('Success:', result),
  onError: (error) => console.error('Error:', error)
});

Custom Provider Integration

Use BaseOAuthButton with any OAuth 2.0 provider:

import { BaseOAuthButton, OAUTH_PROVIDERS } from 'oauthify';

// Use a pre-configured provider
<BaseOAuthButton
  clientId="YOUR_CLIENT_ID"
  redirectUri="YOUR_REDIRECT_URI"
  provider={OAUTH_PROVIDERS.discord}
>
  Sign in with Discord
</BaseOAuthButton>

// Or configure your own
const customProvider = {
  name: 'custom',
  authUrl: 'https://provider.com/oauth/authorize',
  scope: 'read:user',
  additionalParams: {
    custom_param: 'value'
  }
};

<BaseOAuthButton
  clientId="YOUR_CLIENT_ID"
  redirectUri="YOUR_REDIRECT_URI"
  provider={customProvider}
>
  Sign in with Custom Provider
</BaseOAuthButton>

πŸ”„ Response Handling

Success Response

interface OAuthResponse {
  provider: string;    // 'google' | 'github' | etc.
  code: string;        // Authorization code to exchange for tokens
  state?: string;      // State parameter for CSRF protection
  redirectUri?: string;
}

Error Response

interface OAuthError {
  provider: string;
  error: string;
  error_description?: string;
  state?: string;
}

πŸ›‘οΈ Security Best Practices

  1. Never expose your Client Secret in frontend code
  2. Always exchange authorization codes for tokens on your backend
  3. Validate the state parameter to prevent CSRF attacks
  4. Use HTTPS in production
  5. Implement PKCE for public clients (mobile/SPA)
  6. Store tokens securely (httpOnly cookies recommended)

🎨 Styling

All buttons accept standard React props and can be styled:

<GoogleLoginButton
  className="custom-google-btn"
  style={{ padding: '10px 20px' }}
  // ... other props
>
  <CustomIcon />
  <span>Continue with Google</span>
</GoogleLoginButton>

Default CSS classes:

  • .oauth-google-btn
  • .oauth-github-btn
  • .oauth-microsoft-btn
  • .oauth-facebook-btn
  • .oauth-linkedin-btn
  • .oauth-apple-btn

πŸ”§ Advanced Usage

Server-Side Token Exchange

After receiving the authorization code, exchange it for tokens on your backend:

// Example Node.js/Express backend
app.post('/auth/callback', async (req, res) => {
  const { code, provider } = req.body;

  // Exchange code for tokens
  const response = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      code,
      client_id: process.env.GOOGLE_CLIENT_ID,
      client_secret: process.env.GOOGLE_CLIENT_SECRET,
      redirect_uri: process.env.REDIRECT_URI,
      grant_type: 'authorization_code'
    })
  });

  const tokens = await response.json();
  // Store tokens securely and create user session
});

TypeScript Support

OAuthify is built with TypeScript and provides full type definitions:

import type {
  OAuthResponse,
  OAuthError,
  GoogleOAuthConfig,
  MicrosoftOAuthConfig
} from 'oauthify';

// Provider-specific configuration
const googleConfig: GoogleOAuthConfig = {
  name: 'google',
  authUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
  scope: 'openid profile email',
  accessType: 'offline',
  prompt: 'consent'
};

πŸ“Š Bundle Size Comparison

Version Size Reduction
v0.0.32 ~22KB -
v0.0.35 12KB 45% smaller

🀝 Contributing

Contributions are welcome! Please read our Contributing Guide for details.

πŸ“„ License

ISC Β© shekhardtu

πŸ™ Acknowledgments

Built with ❀️ using:

  • React
  • TypeScript
  • Rollup

πŸ”— Links

About

The OAuthify library provides a seamless integration for adding OAuth-based login functionality into your React application. This package comes with pre-built headless components for Google and GitHub login buttons, making the OAuth flow implementation straightforward and efficient.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •