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).
- π 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
npm install oauthify
# or
yarn add oauthify
# or
pnpm add oauthifyWrap your app with OAuthifyProvider:
import { OAuthifyProvider } from 'oauthify';
function App() {
return (
<OAuthifyProvider>
{/* Your app components */}
</OAuthifyProvider>
);
}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 />;
}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>
);
}Each provider requires you to register your application and obtain credentials:
| Provider | Setup Documentation | Required Credentials |
|---|---|---|
| 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 Developers | App ID, App Secret | |
| LinkedIn Developers | Client ID, Client Secret | |
| Apple | Apple Developer | Service ID, Private Key, Team ID |
| Discord | Discord Developers | Client ID, Client Secret |
| Twitter Developer Portal | Client ID, Client Secret | |
| Spotify | Spotify Dashboard | Client ID, Client Secret |
| Slack | Slack API Apps | Client ID, Client Secret |
- Redirect URI: Must match exactly in your app configuration and provider settings
- HTTPS Required: Most providers require HTTPS in production (localhost is usually exempt)
- Scopes: Each provider has different available scopes - check their documentation
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;
}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;
}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;
}Similar interfaces with provider-specific options. See TypeScript definitions for full details.
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();Listen for OAuth responses:
useOAuthListener({
provider: 'google', // Optional: filter by provider
onSuccess: (result) => console.log('Success:', result),
onError: (error) => console.error('Error:', error)
});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>interface OAuthResponse {
provider: string; // 'google' | 'github' | etc.
code: string; // Authorization code to exchange for tokens
state?: string; // State parameter for CSRF protection
redirectUri?: string;
}interface OAuthError {
provider: string;
error: string;
error_description?: string;
state?: string;
}- Never expose your Client Secret in frontend code
- Always exchange authorization codes for tokens on your backend
- Validate the
stateparameter to prevent CSRF attacks - Use HTTPS in production
- Implement PKCE for public clients (mobile/SPA)
- Store tokens securely (httpOnly cookies recommended)
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
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
});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'
};| Version | Size | Reduction |
|---|---|---|
| v0.0.32 | ~22KB | - |
| v0.0.35 | 12KB | 45% smaller |
Contributions are welcome! Please read our Contributing Guide for details.
ISC Β© shekhardtu
Built with β€οΈ using:
- React
- TypeScript
- Rollup