Skip to content
Rishan Solutions
Rishan Solutions
  • PowerApps
  • SharePoint online
    • Uncategorized
    • Uncategorized
  • PowerAutomate
Rishan Solutions
Latest Posts
  • Agentic AI: The Dawn of Autonomous Intelligence Revolutionizing 2025 June 24, 2025
  • Recursive Queries in T-SQL May 7, 2025
  • Generating Test Data with CROSS JOIN May 7, 2025
  • Working with Hierarchical Data May 7, 2025
  • Using TRY_CAST vs CAST May 7, 2025
  • Dynamic SQL Execution with sp_executesql May 7, 2025

OAuth in React

Posted on March 25, 2025March 25, 2025 by Rishan Solutions

Loading

OAuth is the industry standard for authorization, allowing users to log in via third-party services like Google, Facebook, or GitHub without exposing their credentials to your application. Here’s how to implement OAuth in React:

1. OAuth Flow Overview

Authorization Code Flow (Recommended)

  1. User clicks “Login with [Provider]”
  2. Redirect to provider’s authorization page
  3. User authenticates and consents
  4. Redirect back to your app with authorization code
  5. Exchange code for tokens (server-side)
  6. Use tokens to access protected resources

2. Client-Side Implementation

Using react-oauth2-pkce (PKCE Flow)

npm install react-oauth2-pkce
import { AuthProvider, useAuth } from 'react-oauth2-pkce';

const authConfig = {
  clientId: 'YOUR_CLIENT_ID',
  authorizationEndpoint: 'https://provider.com/oauth2/authorize',
  tokenEndpoint: 'https://provider.com/oauth2/token',
  redirectUri: 'http://localhost:3000/callback',
  scope: 'openid profile email',
};

function App() {
  return (
    <AuthProvider authConfig={authConfig}>
      <AuthContent />
    </AuthProvider>
  );
}

function AuthContent() {
  const { authService } = useAuth();

  const login = async () => {
    authService.authorize();
  };

  const logout = () => {
    authService.logout();
  };

  if (authService.isPending()) {
    return <div>Loading...</div>;
  }

  if (!authService.isAuthenticated()) {
    return (
      <div>
        <button onClick={login}>Login</button>
      </div>
    );
  }

  return (
    <div>
      <p>Welcome {authService.getUser().name}!</p>
      <button onClick={logout}>Logout</button>
    </div>
  );
}

3. Server-Side Flow (More Secure)

Frontend Component

function OAuthLogin() {
  const handleLogin = (provider) => {
    // Redirect to your backend OAuth endpoint
    window.location.href = `http://your-backend.com/auth/${provider}`;
  };

  return (
    <div>
      <button onClick={() => handleLogin('google')}>
        Login with Google
      </button>
      <button onClick={() => handleLogin('github')}>
        Login with GitHub
      </button>
    </div>
  );
}

Callback Handler

import { useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';

function OAuthCallback() {
  const location = useLocation();
  const navigate = useNavigate();

  useEffect(() => {
    const params = new URLSearchParams(location.search);
    const code = params.get('code');
    const error = params.get('error');

    if (error) {
      console.error('OAuth error:', error);
      navigate('/login');
      return;
    }

    if (code) {
      // Exchange code for token
      fetch('/api/auth/token', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ code }),
      })
        .then(response => response.json())
        .then(data => {
          // Store tokens and user data
          localStorage.setItem('access_token', data.access_token);
          localStorage.setItem('user', JSON.stringify(data.user));
          navigate('/dashboard');
        })
        .catch(err => {
          console.error('Token exchange failed:', err);
          navigate('/login');
        });
    }
  }, [location, navigate]);

  return <div>Processing login...</div>;
}

4. Popular OAuth Providers

Google OAuth

function GoogleLogin() {
  const handleGoogleLogin = () => {
    const clientId = 'YOUR_GOOGLE_CLIENT_ID';
    const redirectUri = encodeURIComponent('http://localhost:3000/auth/google/callback');
    const scope = encodeURIComponent('openid profile email');
    const url = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=${scope}&access_type=offline&prompt=consent`;

    window.location.href = url;
  };

  return <button onClick={handleGoogleLogin}>Login with Google</button>;
}

GitHub OAuth

function GitHubLogin() {
  const handleGitHubLogin = () => {
    const clientId = 'YOUR_GITHUB_CLIENT_ID';
    const redirectUri = encodeURIComponent('http://localhost:3000/auth/github/callback');
    const scope = encodeURIComponent('user:email');
    const url = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}`;

    window.location.href = url;
  };

  return <button onClick={handleGitHubLogin}>Login with GitHub</button>;
}

5. Token Management

Secure Storage

// Secure token storage with httpOnly cookies is preferred
// If using localStorage:
const storeTokens = (accessToken, refreshToken) => {
  localStorage.setItem('access_token', accessToken);
  localStorage.setItem('refresh_token', refreshToken);
};

const getAccessToken = () => {
  return localStorage.getItem('access_token');
};

const clearTokens = () => {
  localStorage.removeItem('access_token');
  localStorage.removeItem('refresh_token');
};

Token Refresh

async function refreshAccessToken(refreshToken) {
  try {
    const response = await fetch('/api/auth/refresh', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ refresh_token: refreshToken }),
    });

    const data = await response.json();
    storeTokens(data.access_token, data.refresh_token);
    return data.access_token;
  } catch (error) {
    clearTokens();
    throw error;
  }
}

// Axios interceptor example
axios.interceptors.response.use(
  response => response,
  async error => {
    const originalRequest = error.config;
    if (error.response.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      const refreshToken = localStorage.getItem('refresh_token');
      const newToken = await refreshAccessToken(refreshToken);
      originalRequest.headers.Authorization = `Bearer ${newToken}`;
      return axios(originalRequest);
    }
    return Promise.reject(error);
  }
);

6. OAuth with Firebase

import { getAuth, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';

function FirebaseOAuth() {
  const auth = getAuth();

  const signInWithGoogle = () => {
    const provider = new GoogleAuthProvider();
    signInWithPopup(auth, provider)
      .then((result) => {
        // User signed in
        const credential = GoogleAuthProvider.credentialFromResult(result);
        const token = credential.accessToken;
        const user = result.user;
      })
      .catch((error) => {
        console.error('Login error:', error);
      });
  };

  return <button onClick={signInWithGoogle}>Sign in with Google</button>;
}

7. Best Practices

  1. Security:
  • Always use HTTPS
  • Implement PKCE for public clients
  • Store tokens securely (preferably in httpOnly cookies)
  • Validate ID tokens on the server
  1. UX:
  • Handle errors gracefully
  • Provide clear loading states
  • Implement session timeout handling
  • Offer multiple OAuth providers
  1. Performance:
  • Lazy load OAuth libraries when needed
  • Cache user info appropriately
  • Minimize required scopes
  1. Compliance:
  • Follow provider’s branding guidelines
  • Implement proper logout functionality
  • Provide privacy policy and terms links

8. Troubleshooting Common Issues

CORS Problems

// Backend should allow your frontend origin
const corsOptions = {
  origin: ['http://localhost:3000', 'https://your-production-domain.com'],
  credentials: true
};
app.use(cors(corsOptions));

State Parameter

// Always include state parameter to prevent CSRF
const generateState = () => {
  return Math.random().toString(36).substring(2, 15) + 
         Math.random().toString(36).substring(2, 15);
};

const handleLogin = () => {
  const state = generateState();
  localStorage.setItem('oauth_state', state);
  const url = `https://provider.com/oauth?client_id=YOUR_ID&redirect_uri=...&state=${state}`;
  window.location.href = url;
};

// In callback handler
const params = new URLSearchParams(location.search);
const state = params.get('state');
const savedState = localStorage.getItem('oauth_state');

if (state !== savedState) {
  // Possible CSRF attack
  console.error('State mismatch');
  return;
}

Token Expiration

// Decode JWT to check expiration
function isTokenExpired(token) {
  if (!token) return true;
  try {
    const payload = JSON.parse(atob(token.split('.')[1]));
    return payload.exp * 1000 < Date.now();
  } catch (e) {
    return true;
  }
}

OAuth provides a secure way to authenticate users without handling passwords directly. Choose the implementation that best fits your security requirements and application architecture. For most production applications, the server-side flow with PKCE is recommended for better security.

Posted Under ReactJSExpress Google Login Google OAuth JWT OAuth OAuth Flow OAuth Integration React React Authentication React login React security Social Login token authentication

Post navigation

The $scope object in controllers
Sharing data between controllers

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Agentic AI: The Dawn of Autonomous Intelligence Revolutionizing 2025
  • Recursive Queries in T-SQL
  • Generating Test Data with CROSS JOIN
  • Working with Hierarchical Data
  • Using TRY_CAST vs CAST

Recent Comments

  1. Michael Francis on Search , Filter and Lookup in power apps
  2. A WordPress Commenter on Hello world!

Archives

  • June 2025
  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • March 2024
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • June 2023
  • May 2023
  • April 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • January 2022

Categories

  • Active Directory
  • AI
  • AngularJS
  • Blockchain
  • Button
  • Buttons
  • Choice Column
  • Cloud
  • Cloud Computing
  • Data Science
  • Distribution List
  • DotNet
  • Dynamics365
  • Excel Desktop
  • Extended Reality (XR) – AR, VR, MR
  • Gallery
  • Icons
  • IoT
  • Java
  • Java Script
  • jQuery
  • Microsoft Teams
  • ML
  • MS Excel
  • MS Office 365
  • MS Word
  • Office 365
  • Outlook
  • PDF File
  • PNP PowerShell
  • Power BI
  • Power Pages
  • Power Platform
  • Power Virtual Agent
  • PowerApps
  • PowerAutomate
  • PowerPoint Desktop
  • PVA
  • Python
  • Quantum Computing
  • Radio button
  • ReactJS
  • Security Groups
  • SharePoint Document library
  • SharePoint online
  • SharePoint onpremise
  • SQL
  • SQL Server
  • Template
  • Uncategorized
  • Variable
  • Visio
  • Visual Studio code
  • Windows
© Rishan Solutions 2025 | Designed by PixaHive.com.
  • Rishan Solutions