Implementing Google Drive API authentication with service account in React Native Expo application

I’m working on a React Native Expo project and need to connect to Google Drive API using a service account. My goal is to read files from a specific folder in Google Drive without requiring user login.

I’ve already set up a Google service account with editor permissions and shared the target folder with this account. I’m using Expo development build rather than Expo Go.

I keep running into issues when trying to implement the authentication. I’ve tried using the ‘google-auth-library’ package but I get a “prototype may only be an Object or null: undefined” error when testing in the browser. The error only appears when I include the authentication code.

The Expo docs point to “@react-native-google-signin/google-signin” but that seems designed for user authentication, not service accounts.

Here’s my current implementation:

import { Constants } from 'expo-constants';
import { GoogleAuth } from 'google-auth-library';
import fetch from 'axios';

// Get service account details from configuration
const {
  PROJECT_ID,
  SERVICE_EMAIL,
  PRIVATE_KEY_DATA,
  KEY_ID,
  CLIENT_IDENTIFIER,
} = Constants.expoConfig?.extra || {};

// Format private key to handle escaped characters
const formattedPrivateKey = PRIVATE_KEY_DATA.replace(/\\n/g, '\n');

/**
 * Function to authenticate with Google Drive API and get access token
 * @returns {Promise<string>} Access token for API calls
 */
export const getGoogleDriveToken = async (): Promise<string> => {
  try {
    if (!SERVICE_EMAIL || !PRIVATE_KEY_DATA || !PROJECT_ID) {
      throw new Error('Service account configuration missing');
    }

    console.log("Initializing GoogleAuth");
    console.log("Service Email: ", SERVICE_EMAIL);
    console.log("Private Key: ", formattedPrivateKey);
    console.log("Project ID: ", PROJECT_ID);

    // Create authentication object with service account credentials
    const googleAuth = new GoogleAuth({
        credentials: {
          type: 'service_account',
          project_id: PROJECT_ID,
          private_key: formattedPrivateKey,
          client_email: SERVICE_EMAIL,
        },
        scopes: ['https://www.googleapis.com/auth/drive'],
      });
      
    const authClient = await googleAuth.getClient();
    const accessToken = await authClient.getAccessToken();

    if (!accessToken.token) {
      throw new Error('Failed to retrieve access token');
    }

    return accessToken.token;
  } catch (error) {
    console.error('Google authentication error:', error);
    throw error;
  }
};

How can I properly authenticate with Google Drive API using a service account in Expo? Any suggestions for alternative approaches would be helpful.

I ran into similar issues when implementing service account auth in RN. The problem is that google-auth-library relies on Node.js crypto modules that aren’t available in React Native environment. What worked for me was implementing the JWT flow manually using react-native-crypto and expo-crypto for signing operations. You basically need to create a JWT token with your service account credentials, sign it with the private key, then POST it to Google’s token endpoint to get the access token. Another approach I’ve seen work is handling the authentication on a backend service and just calling your own API from the app - this avoids all the crypto compatibility issues entirely and keeps your service account keys more secure since they’re not bundled with the client app.

Had this exact problem last month and spent way too much time debugging it. The core issue is that Expo’s web environment doesn’t support the Node.js modules that google-auth-library depends on, even though it works fine on mobile devices. Instead of fighting with polyfills, I ended up using the googleapis package directly with manual token management. You can create a simple function that builds the JWT assertion manually using expo-crypto for the signing part, then make a direct HTTP request to https://oauth2.googleapis.com/token to exchange it for an access token. Just make sure to cache the token since it’s valid for an hour - no need to regenerate it on every API call. Also double check that your service account JSON structure matches exactly what Google expects, including the token_uri field.

the google-auth-library package doesnt work well in react native enviroment because of node.js dependencies. you’ll need to handle the jwt token generation manually using jose or similar lib. create the jwt payload with service account creds and sign it, then exchange for access token via google’s oauth endpoint.