Introduction
The AWS credentials should never be exposed directly on the client - it could expose access to the entire S3 bucket to the user. For this tutorial we have therefore decided to use the following workflow:- Client makes an API call to the app backend, using the client credentials (a Supabase Edge Function).
- The backend API has the S3 credentials. It signs a S3 upload/download URL, and returns that to the client.
- The client uploads/downloads using the pre-signed S3 URL.
- Create Supabase Edge Functions, and
- Update the demo app to use the AWS S3 storage adapter
The following pre-requisites are required to complete this tutorial:
- Clone the To-Do List demo app repo
- Follow the instructions in the README and ensure that the app runs locally
- A running PowerSync Service (can be self-hosted)
Steps
Step 1: AWS S3 Setup
Step 1: AWS S3 Setup
This tutorial assumes that you have an AWS account. If you do not have an AWS account, you can create one here.
1
Create an S3 Bucket
- Go to the S3 Console and click
Create bucket
. - Enter a unique bucket name and select your preferred region.
- Under
Object Ownership
, set ACLs disabled and ensure the bucket is private. - Enable Bucket Versioning if you need to track changes to files (optional).
2
Configure Permissions
Go to the Permissions tab and set up the following:
- A bucket policy for access control
- Click Bucket policy and enter a policy allowing the necessary actions (e.g., s3:PutObject, s3:GetObject) for the specific users or roles.
- (Optional) Configure CORS (Cross-Origin Resource Sharing) if your app requires it
3
Create an IAM User
- Go to the IAM Console and create a new user with programmatic access.
- Attach an AmazonS3FullAccess policy to this user, or create a custom policy with specific permissions for the bucket.
- Save the Access Key ID and Secret Access Key.
Step 2: Create Supabase Edge Functions
Step 2: Create Supabase Edge Functions
We need to create 3 Supabase Edge Functions to handle the S3 operations:For more information on getting started with a Supabase Edge Function, see the Supabase Getting Started Guide.
- Upload,
- Download, and
- Delete
.env
file in the root of your Supabase project, add and update
the values with your AWS S3 configuration created in Step 1:.env
Security NoteThe filename specified in each edge function request can pose security risks, such as enabling a user to overwrite another user’s files by using the same filename.
To mitigate this, a common approach is to generate a random prefix or directory for each file.
While it’s likely fine to omit this safeguard in the demo — since users can already read and delete any file — this should be addressed in a production environment.
Upload Edge Function
Upload Edge Function
Create the
s3-upload
Edge Function by running the following in your Supabase project:index.ts
Download Edge Function
Download Edge Function
Create the
s3-download
Edge Function by running the following in your Supabase project:index.ts
Delete Edge Function
Delete Edge Function
Create the
s3-delete
Edge Function by running the following in your Supabase project:index.ts
Step 3: Add AWS Storage Adapter
Step 3: Add AWS Storage Adapter
Create a
AWSStorageAdapter.ts
file in the demos/react-native-supabase-todolist/library/storage
directory and add the following contents:Code
Code
AWSStorageAdapter.ts
Explanation
Explanation
The
Two-step deletion process:
AWSStorageAdapter
class implements a storage adapter for AWS S3, allowing file operations (upload, download, delete) with an S3 bucket.uploadFile
uploadFile
- Invokes the
s3-upload
Edge Function to get a pre-signed URL to upload the file - Converts the input ArrayBuffer to an Uint8Array for S3 compatibility
- Uploads the file with metadata (content type) to the pre-signed upload URL
downloadFile
downloadFile
- Invokes the
s3-download
Edge Function to get a pre-signed URL to download the file
- Fetch the file from S3 using the pre-signed URL and converts the response to a Blob for client-side usage
deleteFile
deleteFile
- Delete local file if it exists (using Expo’s FileSystem)
- Delete remote file from S3 by invoking the
s3-delete
Edge Function
Step 4: Use AWS Storage Adapter
Step 4: Use AWS Storage Adapter
Update the
system.ts
file in the demos/react-native-supabase-todolist/library/config
directory to use the new AWSStorageAdapter
class (the highlighted lines are the only changes needed):system.ts
Step 5: Run the app
Step 5: Run the app
Ensure that all references to
AppConfig.supabaseBucket
is replaced with the S3 bucket name in the React Native To-Do List demo app.Obtaining the S3 bucket name in the client can be done by creating another Supabsae Edge Function that returns the bucket name. This ensures that all S3 information are
kept on the server.