DEV Community

Tapan Kumar Swain
Tapan Kumar Swain

Posted on

Google Drive Integration: From OAuth Setup to Background Sync

Integrating Google Drive isn't just about adding a "File Upload" button. It's about building a seamless, automated bridge between your user's cloud universe and your application's logic.

This guide will walk you through everything from clicking the first button in the Google Console to handling background token refreshes like a pro.

Table Of Contents


1: The Foundation (Google Cloud Console)

Before we write a single line of code, we need to tell Google who we are.

Click here for the step-by-step Console setup

1. Create Your Project

  1. Head over to the Google Cloud Console.
  2. Create a New Project. Give it a name you'll recognize, like My-Awesome-App-Sync.
  3. The ID Card: Once created, go to the Dashboard and find your Project Number.
  4. In our code, this is: NEXT_PUBLIC_GOOGLE_APP_ID.

2. Turn on the "Lights" (Enable APIs)

Your project starts empty. You need to enable the specific tools we'll use:

  1. Go to Library.
  2. Search and Enable:
    • Google Drive API: For the backend to read/sync files.
    • Google Picker API: For that beautiful file-selection popup on the frontend.

3. The "Permissions" Screen (OAuth Consent)

  1. Go to OAuth consent screen.
  2. Choose External (standard for most apps).
  3. Fill in your App Name and Support Email.
  4. Scopes: This is crucial. Add https://www.googleapis.com/auth/drive.readonly. This tells the user exactly what you'll be doing (only reading files, not deleting them!).

4. Getting Your Keys (Credentials)

You need two things here:

A. OAuth 2.0 Client ID

  1. Create Credentials > OAuth client ID.
  2. Application type: Web application.
  3. Origins: http://localhost:port (for dev).
  4. Redirect URIs: http://localhost:port/route_name.

B. API Key

  1. Create Credentials > API Key.
  2. Restrict it: Under "API restrictions", select Google Picker API. This ensures your key can't be stolen and used for other expensive services.


2: The Environment Map

Take those keys and drop them into your .env files. We use a card here to keep your configuration organized.

πŸ”‘ Environment Variables

Backend (backend/.env)

env
GOOGLE_CLIENT_ID="xxx-yyy.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET="GOCSPX-your-secret"
GOOGLE_CALLBACK_URL="http://localhost:port/route_name"
Frontend (frontend/.env)

NEXT_PUBLIC_GOOGLE_CLIENT_ID="xxx-yyy.apps.googleusercontent.com"
NEXT_PUBLIC_GOOGLE_API_KEY="AIza-your-api-key"
NEXT_PUBLIC_GOOGLE_APP_ID="your-project-number
Enter fullscreen mode Exit fullscreen mode

3: The OAuth "Handshake" (How it Works)

This is where the magic happens. We use a Hybrid Flow for maximum security and longevity.

  1. The Frontend "Ask" The user clicks "Connect". We use the Google Identity Services (GIS) library to open a popup.

Initialization URL: https://accounts.google.com/gsi/client

const client = google.accounts.oauth2.initCodeClient({
  client_id: GOOGLE_CONFIG.CLIENT_ID,
  scope: 'https://www.googleapis.com/auth/drive.readonly',
  ux_mode: 'popup',
  callback: (response) => {
    // This gives us an 'authorization_code'
    sendCodeToBackend(response.code);
  },
});
client.requestCode();
Enter fullscreen mode Exit fullscreen mode
  1. The Backend "Exchange" Your frontend sends that code to your backend. Your backend then talks to Google privately to get the "Keys to the Kingdom."

Token Exchange URL: POST https://oauth2.googleapis.com/token

Example Request (Node.js/Fetch):

const response = await fetch('https://oauth2.googleapis.com/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    code: authCodeFromFrontend,
    client_id: process.env.GOOGLE_CLIENT_ID,
    client_secret: process.env.GOOGLE_CLIENT_SECRET,
    redirect_uri: 'postmessage', // Crucial for GIS popup flow
    grant_type: 'authorization_code',
  }),
});

const tokens = await response.json(); 

// Returns: access_token, refresh_token, expires_in (usually 3599)
Enter fullscreen mode Exit fullscreen mode

4: The "Eternal" Connection (Token Refresh)

Google's access_token is like a temporary passβ€”it expires in 1 hour (3600 seconds). To keep syncing files while the user is asleep, you need the refresh_token.

How to get a new Access Token
When your database shows the expiresAt is near, or you get a 401 Unauthorized from Google, call this:

Token Refresh URL: POST https://oauth2.googleapis.com/token

Example Request:

const params = new URLSearchParams({
  grant_type: 'refresh_token',
  refresh_token: encryptedStoredRefreshToken,
  client_id: process.env.GOOGLE_CLIENT_ID,
  client_secret: process.env.GOOGLE_CLIENT_SECRET,
});

const response = await fetch('https://oauth2.googleapis.com/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: params.toString(),
});

const data = await response.json(); // New access_token received!
Enter fullscreen mode Exit fullscreen mode

// Update your DB with the new token and new expiry time

Note: Always refresh the token 5-10 minutes before it expires to account for network lag and ensure your background jobs never fail.
Enter fullscreen mode Exit fullscreen mode

5: The Sync Engine (Architecture)

Once authenticated, our platform uses a Recursive Crawler to map the user's Drive.

  • Recursive Traversal: Google Drive is "flat." We start at the folder the user picked and recursively call drive.files.list for every sub-folder.
  • Encryption at Rest: We never store raw tokens. Everything is encrypted using AES-256-GCM before hitting the database.
  • Background Jobs: We queue the files for processing so the user doesn't have to wait for the sync to finish.

Best Practices Checklist

The "Pro" Checklist:

  • [x] Restrict API Keys: Limit your key to the "Google Picker API" only in the Google Console.
  • [x] Encrypt Everything: Store tokens using AES-256-GCM or a similar standard.
  • [x] Offline Access: Always ensure you are requesting access_type: 'offline' to receive that vital refresh token.

Critical Mistakes:

  • Never commit your GOOGLE_CLIENT_SECRET to GitHub or expose it in frontend code.
  • Never hardcode your redirect URIs; always use environment variables to switch between dev and production.
  • Don't Forget: Handle the case where a user revokes access from their Google Account settings manually.

Top comments (0)