Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Integrate Google Drive for File Storage in FlutterFlow

Integrate FlutterFlow with Google Drive API v3 using OAuth to access users' personal Drive. Set up a Cloud Function to handle the OAuth token exchange and file uploads. Use the API Group https://www.googleapis.com/drive/v3/ with a Bearer token for files.list, files.get, and files.delete operations. Always request the drive.file scope (app-created files only) rather than full drive access.

What you'll learn

  • How to implement Google OAuth in FlutterFlow using the google_sign_in package to get a Drive access token
  • How to configure the Google Drive API v3 API Group in FlutterFlow's API Manager with Bearer token auth
  • How to display a user's Drive files in a ListView with type-specific icons and formatted file sizes
  • How to upload files to Google Drive via a Cloud Function and download files using Launch URL
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner12 min read45-60 minFlutterFlow Pro+ (Custom Actions required for OAuth flow)March 2026RapidDev Engineering Team
TL;DR

Integrate FlutterFlow with Google Drive API v3 using OAuth to access users' personal Drive. Set up a Cloud Function to handle the OAuth token exchange and file uploads. Use the API Group https://www.googleapis.com/drive/v3/ with a Bearer token for files.list, files.get, and files.delete operations. Always request the drive.file scope (app-created files only) rather than full drive access.

Access users' Google Drive files from FlutterFlow with OAuth and Drive API v3

Google Drive integration lets your FlutterFlow app read, upload, and manage files in a user's personal Google Drive — useful for document management apps, backup features, file-sharing workflows, and any app where users already store their data in Drive. Unlike Firebase Storage (which stores files in your app's bucket), Google Drive stores files in the user's own Google account. This requires OAuth authorization — the user grants your app specific permission to access their Drive. This tutorial walks through implementing the OAuth flow with the google_sign_in package, setting up the Drive API v3 endpoints in FlutterFlow, building a file browser ListView, handling uploads through a Cloud Function, and downloading files with Launch URL.

Prerequisites

  • A FlutterFlow project with Firebase/Firestore connected (for storing file metadata)
  • A Google Cloud project with the Google Drive API enabled (console.cloud.google.com → APIs & Services → Enable APIs)
  • OAuth 2.0 credentials configured in Google Cloud Console for your app's bundle IDs
  • FlutterFlow Pro plan for Custom Actions (required for OAuth flow)
  • Basic understanding of Cloud Functions for the file upload step

Step-by-step guide

1

Enable Google Drive API and configure OAuth credentials

In Google Cloud Console (console.cloud.google.com), open your Firebase project (the same one linked to FlutterFlow). Go to APIs & Services → Library and search for Google Drive API — click Enable. Then go to APIs & Services → Credentials → Create Credentials → OAuth 2.0 Client IDs. Create one client for iOS (enter your iOS bundle ID from FlutterFlow Settings → App Details) and one for Android (enter your package name and the SHA-1 fingerprint from your keystore). Download the GoogleService-Info.plist updates if prompted. Back in FlutterFlow, the google_sign_in package is already included when Firebase is connected — you do not need to add it to Pubspec Dependencies. Configure the OAuth consent screen: APIs & Services → OAuth consent screen, set the scopes to https://www.googleapis.com/auth/drive.file (app-created files) or https://www.googleapis.com/auth/drive.readonly (read-only browsing).

Expected result: Drive API is enabled, OAuth credentials created for both iOS and Android, and consent screen configured with the correct scope.

2

Implement the Google OAuth sign-in flow with google_sign_in

Create a Custom Action named signInWithGoogleDrive. In the Dart code: import 'package:google_sign_in/google_sign_in.dart'; then create a GoogleSignIn instance with the drive.file scope: final googleSignIn = GoogleSignIn(scopes: ['https://www.googleapis.com/auth/drive.file']); Call final account = await googleSignIn.signIn(); then final auth = await account!.authentication; Store auth.accessToken in FlutterFlow App State as a String named driveAccessToken. Also store account.email as driveUserEmail. Create a second Custom Action signOutGoogleDrive that calls googleSignIn.signOut() and clears the App State variables. Add a Sign in with Google button on your Drive integration page — On Tap calls signInWithGoogleDrive. Show a Conditional Visibility container with the file browser only when driveAccessToken is not empty.

google_drive_auth.dart
1// Custom Action: signInWithGoogleDrive
2import 'package:google_sign_in/google_sign_in.dart';
3
4Future signInWithGoogleDrive() async {
5 final googleSignIn = GoogleSignIn(
6 scopes: [
7 'https://www.googleapis.com/auth/drive.file',
8 ],
9 );
10
11 try {
12 final account = await googleSignIn.signIn();
13 if (account == null) return; // User cancelled
14
15 final auth = await account.authentication;
16 final accessToken = auth.accessToken;
17
18 if (accessToken != null) {
19 // Store in App State
20 FFAppState().driveAccessToken = accessToken;
21 FFAppState().driveUserEmail = account.email;
22 }
23 } catch (e) {
24 print('Google Drive sign in error: $e');
25 }
26}
27
28// Custom Action: signOutGoogleDrive
29Future signOutGoogleDrive() async {
30 final googleSignIn = GoogleSignIn();
31 await googleSignIn.signOut();
32 FFAppState().driveAccessToken = '';
33 FFAppState().driveUserEmail = '';
34 FFAppState().driveFiles = [];
35}

Expected result: Users can sign in with their Google account and grant Drive access. The access token is stored in App State for API calls.

3

Configure the Drive API v3 API Group and list files endpoint

In FlutterFlow → API Manager → Add API Group, name it GoogleDriveAPI. Set the Base URL to https://www.googleapis.com/drive/v3. Under Headers, add Authorization with value Bearer [driveAccessToken] — use Set from Variable to reference the App State driveAccessToken variable. Add an endpoint named listFiles with Method GET and path /files. Add query parameters: q (file filter, e.g., trashed=false), fields (fields: 'files(id,name,mimeType,size,modifiedTime,webContentLink,webViewLink)'), orderBy (modifiedTime desc), pageSize (20). Leave the q parameter empty to list all non-trashed files, or set it to mimeType='application/vnd.google-apps.folder' to list only folders. Test the endpoint — it should return a files array. Create a listFilesByType endpoint with q parameter set to mimeType contains 'image' for image files, or mimeType='application/pdf' for PDFs.

Expected result: API Group is configured with Bearer token auth. listFiles endpoint returns the user's Drive files with metadata.

4

Build the file browser ListView with type icons

Create a DriveFileBrowser page. Add a Backend Query using the listFiles API endpoint, passing the driveAccessToken from App State as the Authorization header variable. Add a ListView bound to the query result's files array. Create a DriveFileRow Component with these elements: a Container (40×40, rounded, colored by file type) with an Icon inside — use Conditional Value to pick the icon based on mimeType: Icons.folder for vnd.google-apps.folder, Icons.image for image/, Icons.picture_as_pdf for application/pdf, Icons.description for vnd.google-apps.document, Icons.table_chart for vnd.google-apps.spreadsheet, Icons.insert_drive_file for everything else. Next to the icon Container: a Column with Text for name (bold, maxLines: 1, overflow: ellipsis) and a Row with Text for the formatted file size (Custom Function: bytes to KB/MB) and Text for modifiedTime (formatted with Custom Function). On the right: an IconButton (Icons.download) that triggers a Launch URL action with webContentLink. Add a Row at the top with a Search TextField — bind the q parameter to contain the search query.

Expected result: File browser displays the user's Drive files with type-appropriate icons, file size, modification date, and a download button.

5

Upload files to Google Drive via Cloud Function

Google Drive's multipart upload requires sending file content and metadata in a single request — this is difficult to do correctly from FlutterFlow's API Manager and requires handling multipart/form-data boundaries. Use a Cloud Function instead. Create a Cloud Function named uploadToDrive that accepts multipart form data: POST with fields accessToken (the user's Drive token), fileName, mimeType, and the file binary. The Cloud Function uses the googleapis Node.js library to authenticate with the user's token and call drive.files.create with the multipart upload. In FlutterFlow, add a UploadButton widget (FlutterFlowUploadButton) on the DriveFileBrowser page. After the upload completes and you have the file bytes and name, call the uploadToDrive Cloud Function endpoint via an API Call action in the Action Flow, passing the accessToken from App State and the uploaded file data.

upload_to_drive.js
1// Cloud Function: uploadToDrive (Node.js 20)
2const functions = require('firebase-functions');
3const { google } = require('googleapis');
4const Busboy = require('busboy');
5
6exports.uploadToDrive = functions.https.onRequest(async (req, res) => {
7 res.set('Access-Control-Allow-Origin', '*');
8 if (req.method === 'OPTIONS') { res.status(204).send(''); return; }
9
10 // Parse multipart form data
11 const busboy = Busboy({ headers: req.headers });
12 let accessToken = '';
13 let fileName = 'upload';
14 let mimeType = 'application/octet-stream';
15 let fileBuffer = null;
16
17 busboy.on('field', (name, value) => {
18 if (name === 'accessToken') accessToken = value;
19 if (name === 'fileName') fileName = value;
20 if (name === 'mimeType') mimeType = value;
21 });
22
23 busboy.on('file', (name, file) => {
24 const chunks = [];
25 file.on('data', chunk => chunks.push(chunk));
26 file.on('end', () => { fileBuffer = Buffer.concat(chunks); });
27 });
28
29 busboy.on('finish', async () => {
30 const auth = new google.auth.OAuth2();
31 auth.setCredentials({ access_token: accessToken });
32 const drive = google.drive({ version: 'v3', auth });
33
34 const response = await drive.files.create({
35 requestBody: { name: fileName, mimeType },
36 media: { mimeType, body: require('stream').Readable.from(fileBuffer) },
37 fields: 'id, name, webViewLink',
38 });
39
40 res.json({ success: true, file: response.data });
41 });
42
43 busboy.end(req.rawBody);
44});

Expected result: Users can pick a file from their device in FlutterFlow and it uploads to their Google Drive. The file appears in the Drive file browser after refresh.

Complete working example

Google Drive Integration Architecture
1OAuth Setup (one-time):
2 Google Cloud Console
3 Enable Google Drive API
4 OAuth 2.0 Credentials (iOS + Android)
5 Consent Screen Scope: drive.file
6
7App State Variables:
8 driveAccessToken: String
9 driveUserEmail: String
10 driveFiles: List<JSON> (cache)
11
12Custom Actions:
13 signInWithGoogleDrive
14 GoogleSignIn(scopes: ['drive.file']).signIn()
15 Stores auth.accessToken App State
16 signOutGoogleDrive
17 googleSignIn.signOut() + clear App State
18
19API Group: GoogleDriveAPI
20 Base URL: https://www.googleapis.com/drive/v3
21 Header: Authorization: Bearer [driveAccessToken]
22 listFiles: GET /files
23 q: trashed=false (filter)
24 fields: files(id,name,mimeType,size,modifiedTime,
25 webContentLink,webViewLink)
26 orderBy: modifiedTime desc
27 pageSize: 20
28 deleteFile: DELETE /files/{fileId}
29
30DriveFileBrowser Page:
31 Conditional: Show sign-in button if driveAccessToken empty
32 SearchBar TextField re-query with q filter
33 ListView (Backend Query: listFiles)
34 DriveFileRow Component
35 Container (icon, colored by mimeType)
36 Icon (Conditional Value by mimeType)
37 Column
38 Text: name (bold, ellipsis)
39 Row: fileSize + modifiedDate
40 IconButton: Download Launch URL webContentLink
41
42Upload Flow:
43 FlutterFlowUploadButton get file bytes + name
44 API Call: uploadToDrive Cloud Function
45 accessToken (from App State)
46 fileName
47 mimeType
48 file bytes
49 Refresh file list after upload
50
51Cloud Function: uploadToDrive
52 Parses multipart form drive.files.create()
53 Returns { id, name, webViewLink }

Common mistakes

Why it's a problem: Requesting the drive scope (full Google Drive access) instead of drive.file

How to avoid: Request drive.file for apps that only manage files they created, or drive.readonly for apps that only need to browse and download. If your app genuinely needs broader access, apply for verification at Google's OAuth verification process and provide a clear justification.

Why it's a problem: Making Drive API upload calls directly from FlutterFlow's API Manager using multipart upload

How to avoid: Handle all Drive file uploads through a Cloud Function that uses the googleapis Node.js library, which correctly constructs the multipart upload request. The FlutterFlow app sends the file bytes and metadata to the Cloud Function, which handles the Drive API call.

Why it's a problem: Not refreshing the OAuth access token when it expires

How to avoid: In your signInWithGoogleDrive Custom Action, check the token expiry by calling googleSignIn.isSignedIn() on app resume. If the token is expired or about to expire, call googleSignIn.signInSilently() to get a fresh token without showing the consent screen again. Store the refresh timestamp in App State.

Best practices

  • Always request the minimum OAuth scope — use drive.file for app-created files only, not the full drive scope which triggers user distrust and Google verification requirements
  • Handle the silent sign-in case: call googleSignIn.signInSilently() on app start so users who previously authorized do not see the sign-in button again
  • Display a clear explanation of why your app needs Drive access before showing the OAuth consent screen — users are more likely to approve when they understand the benefit
  • Use the webContentLink for direct file downloads and webViewLink to open files in Google Drive's viewer — webContentLink works for actual file downloads, webViewLink opens the Drive UI
  • Cache the file list in App State and refresh only when the user explicitly pulls to refresh or uploads a new file — avoid re-fetching on every page navigation
  • Store uploaded file IDs in Firestore linked to the user's account so your app can reference specific Drive files without needing to search by name
  • Test on both iOS and Android — the google_sign_in OAuth flow has platform-specific behavior, especially around the consent screen appearance and account picker UI

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I am building a FlutterFlow app that needs to integrate with Google Drive API v3. Write me a Flutter Custom Action using the google_sign_in package that signs the user in with the drive.file OAuth scope and stores the access token in a variable. Also write a Firebase Cloud Function in Node.js that accepts an access token, file name, MIME type, and file bytes as multipart form data and uploads the file to the user's Google Drive using the googleapis library.

FlutterFlow Prompt

Create a file browser page connected to my GoogleDriveAPI API Group's listFiles endpoint. Display files in a ListView showing a type icon (different colors for folders, images, PDFs, and documents), the file name, file size in KB/MB, and last modified date. Add a download button that launches the webContentLink URL.

Frequently asked questions

What is the difference between Google Drive and Firebase Storage in FlutterFlow?

Firebase Storage stores files in your app's own Google Cloud bucket — it is your app's storage that you control and pay for. Google Drive stores files in the user's personal Google account — the user owns the files and they count against their Google storage quota, not yours. Use Firebase Storage for app-generated content (profile photos, user uploads that others see). Use Google Drive when users want to access their existing Drive files or sync with their personal storage.

Can I access files that the user did not create with my app using drive.file scope?

No. The drive.file scope only allows your app to see and manage files that were created or opened by your app. If you need to browse the user's entire Drive including pre-existing files, you need the drive.readonly scope (read-only) or full drive scope (read-write). Both require additional OAuth app verification from Google if you are publishing to production.

How do I show a folder structure instead of a flat file list?

Use the files.list endpoint with the query parameter q set to '{folderId}' in parents to list files in a specific folder. Start with the root folder by querying q=parents in 'root'. When the user taps a folder, pass its id as the new folder parent in the query. Store the navigation stack (array of {id, name} objects) in Page State to enable the breadcrumb back navigation. Use a Custom Action that updates the current folder ID in App State and triggers a re-fetch.

How do I handle file sharing from my FlutterFlow app?

Use the Drive permissions endpoint: POST /drive/v3/files/{fileId}/permissions with role: reader and type: anyone to make a file publicly accessible, or type: user with emailAddress to share with a specific person. Call this via your Cloud Function using the user's access token. After creating the permission, the file's webViewLink becomes shareable. Add a share icon to each DriveFileRow that calls the Cloud Function and then shows the webViewLink in a copy-to-clipboard dialog.

What happens to the OAuth token when the user logs out of the FlutterFlow app?

Clearing the App State driveAccessToken removes the token from your app, but the OAuth authorization remains active in Google's system. Call googleSignIn.disconnect() (not just signOut) to fully revoke your app's access to the user's Drive. Use signOut for regular logouts (user can re-authorize silently), use disconnect when the user explicitly wants to revoke access or unlink their Google Drive account.

Can RapidDev help build a full Google Drive file management app in FlutterFlow?

Yes. A production-grade Drive integration with folder navigation, file preview, offline access, file sharing with permission management, and real-time Drive change notifications requires Cloud Functions and Custom Actions beyond a basic integration. RapidDev can build and maintain the full Drive integration for your app.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.