Serving assets from Storage
Serving assets from Storage
Public buckets#
As mentioned in the Buckets Fundamentals all files uploaded in a public bucket are publicly accessible and benefit a high CDN cache HIT ratio.
You can access them by using this conventional URL:
https://[project_id].supabase.co/storage/v1/object/public/[bucket]/[asset-name]You can also use the Supabase SDK getPublicUrl to generate this URL for you
const { } = ..('bucket').('filePath.jpg').(.)Downloading#
If you want the browser to start an automatic download of the asset instead of trying serving it, you can add the ?download query string parameter.
By default it will use the asset name to save the file on disk. You can optionally pass a custom name to the download parameter as following: ?download=customname.jpg
Programmatic downloads with query parameters#
When using the SDK's download() method, you can pass additional query parameters to customize the download behavior:
import { createClient } from '@supabase/supabase-js'const supabase = createClient('your_project_url', 'your_supabase_api_key')// ---cut---// Download with custom filenameconst { data, error } = await supabase.storage.from('avatars').download('avatar1.png', { download: 'my-custom-name.png',})Private buckets#
Assets stored in a non-public bucket are considered private and are not accessible via a public URL like the public buckets.
You can access them only by:
- Signing a time limited URL on the Server, for example with Edge Functions.
- with a GET request the URL
https://[project_id].supabase.co/storage/v1/object/authenticated/[bucket]/[asset-name]and the user Authorization header
Signing URLs#
You can sign a time-limited URL that you can share with your users by invoking the createSignedUrl method on the SDK.
const { , } = await . .('bucket') .('private-document.pdf', 3600)if () { .(.)}Revoke signed URLs#
You can't revoke individual signed URLs. To invalidate a specific one, delete, move, or rename the underlying object.
Storage signs URLs with a dedicated internal key, separate from your project's Auth JWT signing key. Each project has its own key.
Because of this, signed URLs are not affected by:
- Rotating or revoking the Auth JWT legacy secret or signing key
- Disabling legacy keys in the Supabase Dashboard
- Switching from a shared secret (HS256) to an asymmetric (ES256) signing key
Signed URLs remain valid until their expiry time regardless of any Auth key changes.
To revoke all signed URLs, rotate the signing key by going to the URL Signing Keys page in the Supabase dashboard.
After revoking the active signing key, all existing signed URLs will return an InvalidJWT error, and new signed URLs created after the rotation will be signed using the updated key.
After revoking a key, previously accessed signed URLs can still be served from the CDN cache. If you need to ensure that all previously cached signed URLs are invalidated, you must purge the CDN cache for those objects or buckets.
Lifetime of a URL signing key#
All newly created keys start off as standby keys. A standby key can be rotated to active state, which will make the existing active key become a standby key. There can only ever be exactly one active key and one standby key.
All signed URLs are created using the active key, but URLs signed by either the active or the standby key are considered valid.
When a standby key is revoked, URLs previously signed with that key will no longer be accepted.
At any point, you can move a key from the revoked state back to being a standby key, and then rotate it to active state. This gives you the confidence to revert to an older key if you identify problems with the rotation, such as forgetting to update a component of your application that is relying on a specific key.
The following table lists each key action, the signatures accepted during that action, and its effect.
| Action | Accepted signatures | Description |
|---|---|---|
| Create standby key | Active key only, new key has not created any JWTs yet. | When you initially create a key, after choosing the signing algorithm, it starts out in the standby state. |
| Rotate key | Both keys in the rotation. | Rotation only changes the key used by Supabase Storage to create new signed URLs, but the trust relationship with both keys remains. |
| Revoke key | Only from the current key. | Once all regularly valid signed URLs have expired (or sooner), revoke the previously used key to revoke trust in it. |
| Move to standby from revoked | Current and previously revoked key. | If you've made a mistake or need more time to adjust your application, you can move a revoked key to standby. Follow up with a rotation to ensure Storage starts using the originally revoked key again to create new signed URLs. |