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

How to Set Up a Secure File Sharing System in FlutterFlow

Build a secure file sharing system using Firebase Storage for uploads and Cloud Functions for access-controlled downloads. Files are shared via links with optional password protection and expiry dates. Every download goes through a Cloud Function that verifies the requester's access (userId in sharedWith array or correct password) before generating a short-lived signed URL (15-minute expiry). Never expose permanent Storage download URLs directly. Track download counts and show file owners a dashboard of shared files with access logs.

What you'll learn

  • How to upload files to Firebase Storage and create shareable Firestore records
  • How to generate short-lived signed URLs via Cloud Functions for secure downloads
  • How to add password protection and expiry dates to shared file links
  • How to track download counts and manage shared file access
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner8 min read25-35 minFlutterFlow Pro+ (Cloud Functions for signed URL generation)March 2026RapidDev Engineering Team
TL;DR

Build a secure file sharing system using Firebase Storage for uploads and Cloud Functions for access-controlled downloads. Files are shared via links with optional password protection and expiry dates. Every download goes through a Cloud Function that verifies the requester's access (userId in sharedWith array or correct password) before generating a short-lived signed URL (15-minute expiry). Never expose permanent Storage download URLs directly. Track download counts and show file owners a dashboard of shared files with access logs.

Building Access-Controlled File Sharing in FlutterFlow

Sharing files securely means more than just uploading to cloud storage. Permanent download URLs can be forwarded to anyone, bypassing your access controls. This tutorial builds a sharing system where every download is verified by a Cloud Function that checks permissions, passwords, and expiry before generating a time-limited signed URL.

Prerequisites

  • FlutterFlow project with Firebase authentication
  • Firebase Storage configured with security rules
  • Cloud Functions enabled on your Firebase project
  • Basic understanding of Firebase Storage in FlutterFlow

Step-by-step guide

1

Create the Firestore schema for shared files

Create a shared_files collection with fields: uploaderId (String), filename (String), storagePath (String, the Firebase Storage path), size (int, bytes), mimeType (String), sharedWith (list of Strings, userIds or 'public'), password (String, hashed, optional), expiresAt (Timestamp, optional), downloadCount (int, default 0), createdAt (Timestamp). The storagePath stores the internal Storage path, never the direct download URL. The sharedWith array controls who can access the file. Setting it to ['public'] allows anyone with the link. An optional password adds a second layer of protection. The expiresAt field makes links expire after a set date.

Expected result: Firestore has a shared_files collection with access control, password, and expiry fields.

2

Build the file upload and sharing configuration form

Create an UploadFile page with a FlutterFlowUploadButton configured for the file types you want to support (documents, images, PDFs). After upload, the button returns the Storage file path. Below the upload button, add sharing options: a Switch for public vs private sharing, a TextField for entering userIds or email addresses to share with (for private), a Switch to enable password protection with a TextField for the password, and a DateTimePicker for optional expiry date. The Share button creates the shared_files Firestore document with all configured options and generates a shareable link (your app URL + the shared_files document ID).

Expected result: Users upload files and configure sharing options including access list, optional password, and expiry date.

3

Deploy the Cloud Function for secure download URL generation

Create a Cloud Function called getSecureDownloadUrl that receives the shared file document ID and optionally a password. The function reads the shared_files document from Firestore and performs access checks: verify the requester is authenticated, check if their userId is in the sharedWith array or if sharedWith contains 'public', verify the password hash matches if password protection is enabled, and check if the current time is before expiresAt. If all checks pass, generate a signed URL for the Storage file with a 15-minute expiry using the Firebase Admin SDK's getSignedUrl method. Increment the downloadCount field. Return the signed URL to the client.

get_secure_download_url.js
1// Cloud Function: getSecureDownloadUrl
2const functions = require('firebase-functions');
3const admin = require('firebase-admin');
4const crypto = require('crypto');
5admin.initializeApp();
6
7exports.getSecureDownloadUrl = functions.https
8 .onCall(async (data, context) => {
9 const { fileId, password } = data;
10 const uid = context.auth?.uid;
11
12 const fileDoc = await admin.firestore()
13 .collection('shared_files').doc(fileId).get();
14 if (!fileDoc.exists) throw new functions.https
15 .HttpsError('not-found', 'File not found');
16
17 const file = fileDoc.data();
18
19 // Check expiry
20 if (file.expiresAt && file.expiresAt.toDate() < new Date()) {
21 throw new functions.https
22 .HttpsError('deadline-exceeded', 'Link expired');
23 }
24
25 // Check access
26 const isPublic = file.sharedWith.includes('public');
27 const isAuthorized = uid && file.sharedWith.includes(uid);
28 const isOwner = uid === file.uploaderId;
29 if (!isPublic && !isAuthorized && !isOwner) {
30 throw new functions.https
31 .HttpsError('permission-denied', 'No access');
32 }
33
34 // Check password
35 if (file.password) {
36 const hash = crypto.createHash('sha256')
37 .update(password || '').digest('hex');
38 if (hash !== file.password) {
39 throw new functions.https
40 .HttpsError('permission-denied', 'Wrong password');
41 }
42 }
43
44 // Generate signed URL (15 min expiry)
45 const bucket = admin.storage().bucket();
46 const [url] = await bucket.file(file.storagePath)
47 .getSignedUrl({
48 action: 'read',
49 expires: Date.now() + 15 * 60 * 1000,
50 });
51
52 // Track download
53 await fileDoc.ref.update({
54 downloadCount: admin.firestore.FieldValue.increment(1),
55 });
56
57 return { url };
58 });

Expected result: The Cloud Function verifies access, password, and expiry before returning a 15-minute signed download URL.

4

Build the download page with access verification UI

Create a DownloadPage that receives the fileId as a URL parameter. On Page Load, query the shared_files document to get the filename, size, and whether a password is required. Display the file info: filename, size formatted (KB/MB), and upload date. If the file requires a password, show a TextField for password entry and a Download button. If no password is needed, show the Download button directly. On button tap, call the getSecureDownloadUrl Cloud Function with the fileId and password. On success, launch the returned signed URL to start the download. On error, show the appropriate message (expired, no access, wrong password).

Expected result: The download page shows file info, requests a password if needed, and securely downloads the file.

5

Build the file management dashboard for file owners

Create a MySharedFiles page showing all files uploaded by the current user. Add a ListView bound to shared_files where uploaderId equals the current user's ID, ordered by createdAt descending. Each list item shows: filename, size, download count, expiry date (or 'No expiry'), and the number of people it is shared with. Add action buttons: Copy Link (copies the share URL to clipboard), Edit (modify sharedWith, password, or expiry), and Delete (removes both the Firestore document and the Storage file). This gives file owners full visibility and control over their shared files.

Expected result: File owners see all their shared files with download stats and can manage access, edit settings, or delete files.

Complete working example

FlutterFlow Secure File Sharing System
1FIRESTORE SCHEMA:
2 shared_files (collection):
3 uploaderId: String
4 filename: String
5 storagePath: String (internal Storage path, never direct URL)
6 size: int (bytes)
7 mimeType: String
8 sharedWith: [String] (userIds or 'public')
9 password: String (SHA-256 hash, optional)
10 expiresAt: Timestamp (optional)
11 downloadCount: int (default 0)
12 createdAt: Timestamp
13
14FIREBASE STORAGE RULES:
15 // Block all direct access — downloads go through Cloud Function
16 match /shared/{allPaths=**} {
17 allow read: if false; // No direct reads
18 allow write: if request.auth != null; // Auth users can upload
19 }
20
21PAGE: UploadFile
22 FlutterFlowUploadButton (documents, images, PDFs)
23 Switch: Public / Private
24 TextField: share with userIds (for private)
25 Switch: Password protection + TextField (password)
26 DateTimePicker: expiry date (optional)
27 Button "Share" create shared_files doc + generate link
28
29CLOUD FUNCTION: getSecureDownloadUrl
30 Input: fileId, password (optional)
31 Checks: auth sharedWith password expiresAt
32 On pass: generate 15-min signed URL + increment downloadCount
33 On fail: return specific error (expired/denied/wrong password)
34
35PAGE: DownloadPage (URL param: fileId)
36 On Load: fetch shared_files doc
37 Display: filename, size, upload date
38 If password required: TextField + Download button
39 If no password: Download button directly
40 On tap: call getSecureDownloadUrl Launch URL
41
42PAGE: MySharedFiles
43 ListView: shared_files where uploaderId == currentUser
44 Each item: filename + size + downloads + expiry
45 Actions: Copy Link | Edit | Delete

Common mistakes

Why it's a problem: Using permanent Firebase Storage download URLs for shared files

How to avoid: Block direct Storage access with security rules. Route all downloads through a Cloud Function that generates short-lived signed URLs (15-minute expiry) after verifying permissions.

Why it's a problem: Storing passwords in plaintext in Firestore

How to avoid: Hash passwords with SHA-256 before storing. When verifying, hash the input password and compare hashes. Never store or transmit plaintext passwords.

Why it's a problem: Not checking the expiry date before generating the download URL

How to avoid: Always check if the current time is past expiresAt before generating the signed URL. Return a clear 'Link expired' error message.

Best practices

  • Route all downloads through Cloud Functions instead of using direct Storage URLs
  • Use short-lived signed URLs (15 minutes) to minimize exposure window
  • Hash passwords before storing them in Firestore
  • Track download counts so file owners know how their files are being accessed
  • Block direct Firebase Storage access with security rules that deny all reads
  • Provide clear error messages for expired links, wrong passwords, and access denied
  • Allow file owners to revoke access by removing userIds from the sharedWith array

Still stuck?

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

ChatGPT Prompt

Build a secure file sharing system in FlutterFlow. Files are uploaded to Firebase Storage. Sharing uses Firestore records with access control (sharedWith array), optional password (SHA-256 hashed), and optional expiry date. Downloads go through a Cloud Function that verifies access and generates 15-minute signed URLs. Include the Cloud Function code, Firestore schema, and Storage security rules.

FlutterFlow Prompt

Create a file upload page with a FlutterFlowUploadButton, a Switch for public vs private sharing, a TextField for entering email addresses to share with, a Switch for password protection with a password field, and a DateTimePicker for expiry date.

Frequently asked questions

What file types can I support?

Firebase Storage supports any file type. Configure the FlutterFlowUploadButton's allowed types to match your needs: documents (pdf, docx), images (png, jpg), spreadsheets (xlsx, csv), or any combination. Set a maximum file size to prevent abuse.

Can I share files with people who do not have an account?

Yes. Set the sharedWith array to include 'public' and optionally add a password. Anyone with the link and password can download without authentication. The Cloud Function skips the userId check for public files.

How do I revoke access to a shared file?

Remove the user's ID from the sharedWith array or delete the shared_files document entirely. Since download URLs expire in 15 minutes, revoking access takes effect within that window at most.

Is there a file size limit?

Firebase Storage supports files up to 5TB. However, FlutterFlowUploadButton has practical limits based on mobile network speeds. For large files, consider chunked uploads via a Custom Action.

Can I add download notifications for file owners?

Yes. In the getSecureDownloadUrl Cloud Function, after incrementing downloadCount, create a notification document or send a push notification to the file owner with the downloader's name and timestamp.

Can RapidDev help build secure file management systems?

Yes. RapidDev can build enterprise file sharing with encryption, audit logging, compliance controls, watermarking, and integration with document management platforms.

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.