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".
_10create policy "Public Access"_10on storage.objects_10for select -- Allow read access_10to anon, authenticated -- Allow access to anonymous and authenticated users_10using ( 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:
_10create policy "policy_name"_10ON storage.objects_10for 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:
_10create policy "policy_name"_10on 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
:
_10create policy "Allow authenticated uploads"_10on storage.objects_10for select_10to public_10using (_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
:
_10create policy "Allow authenticated uploads"_10on storage.objects_10for insert_10to authenticated_10with 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
:
_10create policy "Only allow PNG uploads"_10on storage.objects_10for insert_10to authenticated_10with 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:
_10create policy "Public Access"_10on storage.objects for select_10to public_10using ( bucket_id = 'public' );
Allowing logged-in access to a bucket#
Allow logged-in access to any files in the "restricted" bucket:
_10create policy "Restricted Access"_10on storage.objects for select_10to authenticated_10using ( bucket_id = 'restricted' );
Allowing individual access to a file#
Allow a user to access their own files:
_10create policy "Individual user Access"_10on storage.objects for select_10to authenticated_10using ( auth.uid() = owner );