Home

Access Control

Manage who can access your Supabase Storage files.

Supabase Storage is designed to work perfectly with Postgres Row Level Security (RLS).

You can use RLS to create Security Access Policies that are incredibly powerful and flexible, allowing you to restrict access based on your business needs.

Policies#

Policies are just SQL, and they're easy once you get the hang of them. For example, here is a Policy that allows public access to any files in a bucket called "my_bucket_id".


_10
create policy "Public Access"
_10
on storage.objects
_10
for select -- Allow read access
_10
to anon, authenticated -- Allow access to anonymous and authenticated users
_10
using ( bucket_id = 'my_bucket_id' ); -- Identify the bucket

An easy way to get started would be to create RLS policies for SELECT, INSERT, UPDATE, DELETE operations and restrict the policies to meet your security requirements. For example, one can start with the following INSERT policy:


_10
create policy "policy_name"
_10
ON storage.objects
_10
for insert with check (
_10
true
_10
);

and modify it to only allow authenticated users to upload assets to a specific bucket by changing it to:


_10
create policy "policy_name"
_10
on storage.objects for insert to authenticated with check (
_10
-- restrict bucket
_10
bucket_id = 'my_bucket_id'
_10
);

Metadata storage#

Supabase Storage stores metadata in the objects and buckets table in the storage schema.

To allow read access to files, the RLS policy must allow users to SELECT the objects table and for uploading a new object, the RLS policy must grant users access to INSERT into the objects table and so on. The mapping between the different API calls and the database permissions required is documented in the Reference docs.

Public and private buckets#

Storage buckets are private by default. For private buckets, you can access objects via the download method. This corresponds to /object/auth/ API endpoint. Alternatively, you can create a publicly shareable URL with an expiry date using the createSignedUrl method which calls the /object/sign/ API.

For public buckets, you can access the assets directly without a token or an Authorisation header. The getPublicUrl helper method returns the full public URL for an asset. This calls the /object/public/ API endpoint internally. While no authorization is required for accessing objects in a public bucket, proper access control is required for other operations like uploading, deleting objects from public buckets as well.

Public buckets also tend to have better performance.

The URLs to access storage endpoints are prefixed with /storage/v1. For example, on the hosted Platform they will be:

https://[project_ref].supabase.co/storage/v1/object/public/[id]

You can access the storage API directly with the same endpoint. See the API docs for a full list of operations available.

Helper functions#

Supabase Storage provides SQL helper functions which you can use in your database queries and RLS policies.

storage.filename()#

Returns the name of a file. For example, if your file is stored in public/subfolder/avatar.png it would return: 'avatar.png'

Usage

This example demonstrates how you would allow any user to download a file called favicon.ico:


_10
create policy "Allow authenticated uploads"
_10
on storage.objects
_10
for select
_10
to public
_10
using (
_10
storage.filename(name) = 'favicon.ico'
_10
);

storage.foldername()#

Returns an array path, with all of the subfolders that a file belongs to. For example, if your file is stored in public/subfolder/avatar.png it would return: [ 'public', 'subfolder' ]

Usage

This example demonstrates how you would allow authenticated users to upload files to a folder called private:


_10
create policy "Allow authenticated uploads"
_10
on storage.objects
_10
for insert
_10
to authenticated
_10
with check (
_10
storage.foldername(name)[1] = 'private'
_10
);

storage.extension()#

Returns the extension of a file. For example, if your file is stored in public/subfolder/avatar.png it would return: 'png'

Usage

This example demonstrates how you would allow restrict uploads to only PNG files inside a bucket called cats:


_10
create policy "Only allow PNG uploads"
_10
on storage.objects
_10
for insert
_10
to authenticated
_10
with check (
_10
bucket_id = 'cats' and storage.extension(name) = 'png'
_10
);

Usage#

Row Level Security is extremely versatile, since it simply uses SQL to express access rules for your data. You can learn more about RLS in the Database docs.

Allowing public access to a bucket#

Allow public access to any files in the "public" bucket:


_10
create policy "Public Access"
_10
on storage.objects for select
_10
to public
_10
using ( bucket_id = 'public' );

Allowing logged-in access to a bucket#

Allow logged-in access to any files in the "restricted" bucket:


_10
create policy "Restricted Access"
_10
on storage.objects for select
_10
to authenticated
_10
using ( bucket_id = 'restricted' );

Allowing individual access to a file#

Allow a user to access their own files:


_10
create policy "Individual user Access"
_10
on storage.objects for select
_10
to authenticated
_10
using ( auth.uid() = owner );