How to Retrieve Access Token and Google ID After Sign-In with React OAuth Google
Use the useGoogleLogin hook from @react-oauth/google to capture both access_token and id_token from the token response, then pass these values to GoogleAuthProvider.credential() to create a Firebase-compatible OAuth credential that exposes the tokens via credential.accessToken and credential.idToken.
The @react-oauth/google library simplifies Google authentication in React applications, but integrating these credentials with Firebase Auth requires understanding how to extract and convert the tokens. This guide demonstrates how to retrieve both the access token and Google ID token (JWT) after a successful sign-in using the firebase/firebase-js-sdk source code as reference.
Understanding the Token Response Structure
When you invoke the useGoogleLogin hook, the library initiates Google's OAuth 2.0 flow and returns a token response object containing two distinct credentials:
access_token– A short-lived token that authorizes requests to Google APIs (Drive, Calendar, etc.).id_token– A JSON Web Token (JWT) that contains identity claims about the user, including the Google ID (sub claim).
These fields align directly with the parameters expected by Firebase's GoogleAuthProvider.credential() method implemented in packages/auth/src/core/providers/google.ts (lines 93-100).
Extracting Tokens with useGoogleLogin
For applications that only need the raw tokens without Firebase integration, capture the response directly from the hook's callback:
import { useGoogleLogin } from '@react-oauth/google';
export function GoogleSignIn() {
const login = useGoogleLogin({
scope: 'profile email https://www.googleapis.com/auth/drive.readonly',
onSuccess: (tokenResponse) => {
// Extract both tokens from the response
const accessToken = tokenResponse.access_token;
const idToken = tokenResponse.id_token;
console.log('Access Token:', accessToken);
console.log('ID Token:', idToken);
// Decode the JWT to get the Google ID (sub claim)
const payload = JSON.parse(atob(idToken.split('.')[1]));
console.log('Google ID (sub):', payload.sub);
},
onError: (error) => {
console.error('Login Failed:', error);
}
});
return <button onClick={() => login()}>Sign in with Google</button>;
}
The tokenResponse object structure matches the standard Google OAuth 2.0 token response, ensuring compatibility with the Firebase SDK's credential factory methods.
Converting to Firebase Credentials
To integrate with Firebase Auth, pass the extracted tokens to GoogleAuthProvider.credential() and then call signInWithCredential(). According to the source code in packages/auth/src/core/providers/google.ts (lines 10-13), you can later retrieve the credential from the sign-in result using credentialFromResult:
import { useGoogleLogin } from '@react-oauth/google';
import {
getAuth,
signInWithCredential,
GoogleAuthProvider
} from 'firebase/auth';
export function FirebaseGoogleSignIn() {
const auth = getAuth();
const login = useGoogleLogin({
scope: 'profile email'
});
const handleSignIn = async () => {
try {
// Step 1: Get tokens from React OAuth Google
const tokenResponse = await login();
const { id_token: idToken, access_token: accessToken } = tokenResponse;
// Step 2: Create Firebase credential (packages/auth/src/core/providers/google.ts lines 93-100)
const credential = GoogleAuthProvider.credential(idToken, accessToken);
// Step 3: Sign in to Firebase
const userCredential = await signInWithCredential(auth, credential);
// Step 4: Extract tokens from the result (packages/auth/src/core/providers/google.ts lines 10-13)
const retrievedCredential = GoogleAuthProvider.credentialFromResult(userCredential);
console.log('Firebase Access Token:', retrievedCredential?.accessToken);
console.log('Firebase ID Token:', retrievedCredential?.idToken);
console.log('User UID:', userCredential.user.uid);
} catch (error) {
console.error('Authentication error:', error);
}
};
return <button onClick={handleSignIn}>Sign in with Google</button>;
}
This approach leverages the existing token response from @react-oauth/google without requiring additional network calls, as the Firebase SDK simply wraps the provided tokens into an OAuthCredential object.
Alternative: Direct Firebase Popup Flow
If you prefer to bypass @react-oauth/google entirely, the Firebase SDK provides a native popup flow that returns the same tokens. The demo code in packages/auth/demo/src/index.js and packages/auth/demo/public/common.js illustrates this pattern:
import { getAuth, signInWithPopup, GoogleAuthProvider } from 'firebase/auth';
export async function nativeFirebaseSignIn() {
const auth = getAuth();
const provider = new GoogleAuthProvider();
// Request specific scopes
provider.addScope('profile');
provider.addScope('email');
provider.addScope('https://www.googleapis.com/auth/drive.readonly');
try {
const result = await signInWithPopup(auth, provider);
// Extract credential containing both tokens
const credential = GoogleAuthProvider.credentialFromResult(result);
if (credential) {
console.log('Access Token:', credential.accessToken);
console.log('ID Token:', credential.idToken);
}
console.log('User:', result.user);
} catch (error) {
console.error('Sign-in error:', error);
}
}
This method is implemented in the Firebase Auth core and handles the OAuth flow internally, returning the same accessToken and idToken available through the credential object.
Summary
- The
@react-oauth/googlelibrary returns bothaccess_tokenandid_tokenin its token response after a successful sign-in. - Pass these tokens to
GoogleAuthProvider.credential(idToken, accessToken)to create a Firebase-compatible OAuth credential, as implemented inpackages/auth/src/core/providers/google.ts. - Use
signInWithCredential()to authenticate with Firebase, then retrieve the tokens again viaGoogleAuthProvider.credentialFromResult(). - Alternatively, use Firebase's native
signInWithPopup()to obtain the same credentials without external OAuth libraries.
Frequently Asked Questions
What is the difference between the access token and the ID token?
The access token (access_token) is a short-lived credential that authorizes API requests to Google services like Drive or Calendar. The ID token (id_token) is a JWT containing identity claims about the user, including the Google ID (sub claim), email, and profile information. While the access token grants permissions, the ID token proves the user's identity.
Is it safe to store these tokens in localStorage or sessionStorage?
No, storing OAuth tokens in localStorage or sessionStorage exposes them to XSS (Cross-Site Scripting) attacks. The Firebase SDK manages token storage internally using secure mechanisms. If you must handle tokens manually, keep them in memory (React state) and exchange them for Firebase credentials immediately, letting Firebase handle persistence securely.
Can I get a refresh token using the React OAuth Google library?
The @react-oauth/google library uses the Implicit Flow by default, which does not return refresh tokens. To obtain a refresh token, you must use the Authorization Code Flow with a backend server that exchanges the code for tokens including a refresh token. Firebase Auth handles token refresh automatically when you use signInWithCredential, so manual refresh tokens are typically unnecessary for client-side Firebase integrations.
How do I extract the user's Google ID from the ID token?
The Google ID (also called the sub claim) is embedded within the JWT payload of the ID token. Decode the token client-side using JSON.parse(atob(idToken.split('.')[1])) to access the payload object, then read the sub property. Alternatively, after signing into Firebase, access the normalized user ID via userCredential.user.uid, which Firebase maps from the Google sub claim during the credential exchange.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →