Access Control

Storage

Control who can access your files with public/private settings and signed URLs.

Public/Private

Flexible visibility options

Signed URLs

Time-limited secure access

File Sharing

Grant access to other users

CORS Config

Cross-origin uploads

Public vs Private Files

Files can be either public (anyone can access) or private (requires authentication):

// Public file - accessible to anyone with the URL
const publicFile = await upload(file, {
  public: true,
})
// publicFile.url = "https://cdn.sylphx.com/files/abc123.jpg"

// Private file - requires signed URL
const privateFile = await upload(file, {
  public: false, // default
})
// privateFile.signedUrl = "https://cdn.sylphx.com/files/abc123.jpg?token=..."
// URL expires after 1 hour by default

Signed URLs

Generate temporary signed URLs for private files:

import { platform } from '@/lib/platform'

// Get a signed URL that expires in 1 hour (default)
const { url } = await platform.storage.getSignedUrl(fileId)

// Custom expiration (in seconds)
const { url: shortUrl } = await platform.storage.getSignedUrl(fileId, {
  expiresIn: 300, // 5 minutes
})

// Long-lived URL (up to 7 days)
const { url: longUrl } = await platform.storage.getSignedUrl(fileId, {
  expiresIn: 604800, // 7 days
})

URL Security

Anyone with a signed URL can access the file until it expires. Be careful sharing long-lived URLs.

Download URLs

Generate URLs that force file download instead of browser preview:

const { url } = await platform.storage.getSignedUrl(fileId, {
  download: true, // Force download
  downloadFilename: 'report.pdf', // Custom filename
})

File Permissions

Control who can access private files:

// Set file owner (done automatically on upload)
const file = await platform.storage.upload({
  file: buffer,
  filename: 'document.pdf',
  ownerId: user.id, // Only this user can generate signed URLs
})

// Share with another user
await platform.storage.share(fileId, {
  userId: otherUser.id,
  permission: 'read', // 'read' or 'write'
})

// Revoke access
await platform.storage.unshare(fileId, {
  userId: otherUser.id,
})

Change File Visibility

Change a file between public and private:

// Make public
await platform.storage.update(fileId, {
  public: true,
})

// Make private
await platform.storage.update(fileId, {
  public: false,
})

Content-Type Headers

Control how browsers handle files:

// Set content disposition for inline viewing
const { url } = await platform.storage.getSignedUrl(fileId, {
  contentDisposition: 'inline', // View in browser
})

// Set content disposition for download
const { url: downloadUrl } = await platform.storage.getSignedUrl(fileId, {
  contentDisposition: 'attachment; filename="report.pdf"',
})

// Set cache control
const { url: cachedUrl } = await platform.storage.getSignedUrl(fileId, {
  cacheControl: 'public, max-age=3600', // Cache for 1 hour
})

CORS Configuration

Configure CORS for client-side uploads:

// In dashboard: App Settings → Storage → CORS

// Example CORS configuration
{
  "allowedOrigins": [
    "https://myapp.com",
    "https://*.myapp.com",
    "http://localhost:3000"
  ],
  "allowedMethods": ["GET", "PUT", "POST", "DELETE"],
  "allowedHeaders": ["*"],
  "maxAge": 3600
}

Access Patterns

Common access patterns and when to use them:

PropertyTypeDescription
User avatarsPublicpublic: true
Product imagesPublicpublic: true
User documentsPrivate + Signed URLgetSignedUrl()
Invoices/receiptsPrivate + DownloadgetSignedUrl({ download: true })
Shared team filesPrivate + Sharingshare()

Security Best Practices

Default to private

Only make files public when necessary

Short-lived URLs

Use short expiration times for signed URLs

Validate uploads

Check file types and sizes before accepting

Scan for malware

Enable virus scanning in dashboard (Pro+)

Audit access

Monitor file access logs in the dashboard