React OAuth

repository·master·Indexed 23 days ago

https://github.com/momensherif/react-oauth

A collection of production-ready, type-safe OAuth2 libraries for React applications. It provides streamlined integrations for Google and GitHub authentication, including specialized packages like @react-oauth/google and @react-oauth/github. Features include the GoogleLogin component, useGoogleLogin and useGitHubLogin hooks, and support for both implicit and authorization code flows.

Tokens
10.2K
Snippets
26
Records
49
Agent score
79%

What's inside react-oauth

  1. Overview of React OAuth packages

    master

    React OAuth provides production-ready, type-safe OAuth2 libraries for React applications. The repository is split into two primary packages:

    • @react-oauth/google: Implements Google OAuth2 using the modern Google Identity Services SDK. Supports Sign In With Google buttons, one-tap sign-up, automatic sign-in, and both Implicit & Authorization Code flows.
    • @react-oauth/github: A modern React hook for GitHub OAuth authentication. It features zero runtime dependencies, built-in CSRF protection, and complete UI control via a hook-based API.
  2. Manage the playground application with npm scripts

    master

    The playground application is built using Create React App. You can manage the development lifecycle using the following npm commands:

    • Development: Run npm start to launch the app in development mode at http://localhost:3000. The app will automatically reload on file edits.
    • Testing: Run npm test to launch the test runner in interactive watch mode.
    • Production Build: Run npm run build to create a minified, optimized production build in the build folder, ready for deployment.
    • Eject: Run npm run eject to expose the underlying build configuration (webpack, Babel, etc.). Warning: This is a one-way operation and cannot be undone.
    npm start
    npm test
    npm run build
    npm run eject
  3. Install and use @react-oauth/github

    master

    To implement GitHub OAuth authentication, install the @react-oauth/github package.

    Use the useGitHubLogin hook to manage the authentication flow. The hook requires a configuration object containing clientId, redirectUri, onSuccess, and onError. It returns an initiateGitHubLogin function to trigger the flow and an isLoading boolean to track the status.

    Note: The onSuccess callback provides an authorization code which you should exchange for an access token on your backend.

    import { useGitHubLogin } from '@react-oauth/github';
    
    function LoginButton() {
      const { initiateGitHubLogin, isLoading } = useGitHubLogin({
        clientId: 'your-github-client-id',
        redirectUri: 'http://localhost:3000/callback',
        onSuccess: response => {
          console.log('Authorization code:', response.code);
          // Exchange code for access token on your backend
        },
        onError: error => {
          console.error('Authentication failed:', error);
        },
      });
    
      return (
        <button onClick={initiateGitHubLogin} disabled={isLoading}>
          {isLoading ? 'Loading...' : 'Sign in with GitHub'}
        </button>
      );
    }
  4. Configure GoogleOAuthProvider

    master

    To use the library, you must wrap your application with the GoogleOAuthProvider and provide your Google API clientId.

    Prerequisites:

    1. Obtain a Google API client ID from the Google Cloud Console.
    2. Configure your OAuth Consent Screen.
    3. For local development, ensure you add both http://localhost and http://localhost:<port_number> to the Authorized JavaScript origins in your Google Cloud settings.

    Note on Popup Mode: If using the default popup mode, set your server's Cross-Origin-Opener-Policy header to cross-origin-opener-policy: same-origin-allow-popups to prevent blank window issues.

    import { GoogleOAuthProvider } from '@react-oauth/google';
    
    <GoogleOAuthProvider clientId="<your_client_id>">...</GoogleOAuthProvider>;
  5. Install and use @react-oauth/google

    master

    To implement Google OAuth2 using the Google Identity Services SDK, install the @react-oauth/google package.

    Wrap your application (or the relevant part of your component tree) in the GoogleOAuthProvider and provide your clientId. You can then use the GoogleLogin component to render a standard 'Sign In With Google' button. The component provides onSuccess and onError callbacks to handle the authentication lifecycle.

    import { GoogleOAuthProvider, GoogleLogin } from '@react-oauth/google';
    
    function App() {
      return (
        <GoogleOAuthProvider clientId="<your_client_id>">
          <GoogleLogin
            onSuccess={credentialResponse => {
              console.log(credentialResponse);
            }}
            onError={() => {
              console.log('Login Failed');
            }}
          />
        </GoogleOAuthProvider>
      );
    }
  6. Exchange authorization code for access token on your backend

    master

    The onSuccess callback provides an authorization code. Never exchange this code on the client side, as this requires your client_secret. Instead, send the code to your backend and perform a POST request to GitHub's access token endpoint.

    Backend Workflow:

    1. Receive code from frontend.
    2. POST to https://github.com/login/oauth/access_token with client_id, client_secret, and code.
    3. Use the returned access_token to fetch user data from https://api.github.com/user.
    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...
    });
  7. Configure useGitHubLogin options

    master

    The useGitHubLogin hook accepts a UseGitHubLoginOptions object with the following properties:

    OptionTypeRequiredDefaultDescription
    clientIdstring-Your GitHub OAuth App Client ID
    onSuccess(response: OAuthResponse) => void-Callback called when authentication succeeds
    onError(error: Error) => void-Callback called when authentication fails
    redirectUristring''Registered redirect URI for your OAuth App
    scopestring'user:email'OAuth scopes to request (comma-separated)
    popupOptionsPopupWindowOptions-Options for configuring the popup window
    statestringAuto-generatedState parameter for CSRF protection
    allowSignupbooleantrueWhether to allow signup during authentication
    onRequest() => void-Optional callback called when OAuth flow is initiated
  8. Handle GitHub OAuth errors

    master

    Errors returned via onError are Error objects that include a code property of type OAuthErrorCode. You can use OAuthError.isOAuthError(error) to verify the error type and then switch on the error code to handle specific scenarios like popup closures or browser blocks.

    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');
                break;
              case OAuthErrorCode.POPUP_BLOCKED:
                console.log('Popup blocked by browser');
                break;
              case OAuthErrorCode.STATE_MISMATCH:
                console.log('State mismatch - possible CSRF attack');
                break;
              case OAuthErrorCode.MISSING_CODE:
                console.log('Authorization code not found in response');
                break;
              default:
                console.log('Other OAuth error:', error.message);
            }
          } else {
            console.error('Unexpected error:', error);
          }
        },
      });
    
      return (
        <button onClick={initiateGitHubLogin} disabled={isLoading}>
          {isLoading ? 'Loading...' : 'Sign in with GitHub'}
        </button>
      );
    }
  9. Implement custom login buttons with useGoogleLogin

    master

    If you want to use your own UI components instead of the pre-built GoogleLogin button, use the useGoogleLogin hook. This hook supports two flows:

    1. Implicit Flow (Default): Returns an access token directly to the client.
    2. Authorization Code Flow: Returns a code that your backend must exchange for access and refresh tokens. Set flow: 'auth-code' to enable this.

    To enable automatic sign-in for returning users, use the auto_select option.

    import { useGoogleLogin } from '@react-oauth/google';
    
    // Implicit Flow
    const login = useGoogleLogin({
      onSuccess: tokenResponse => console.log(tokenResponse),
    });
    
    // Authorization Code Flow
    const loginWithCode = useGoogleLogin({
      onSuccess: codeResponse => console.log(codeResponse),
      flow: 'auth-code',
    });
    
    <MyCustomButton onClick={() => login()}>Sign in with Google 🚀</MyCustomButton>