Cloud storage connectors
How to connect each cloud source to the Waldrop upload wizard — what credentials to generate, where to get them, and what to paste. Six connectors are production-ready: S3, GCS, Azure, SFTP, Dropbox, and Google Drive.
Cloud-source uploads route through your browser. Your credentials hit Waldrop's server once per request, are used to fetch the file, and are never stored. The fetched bytes are encrypted client-side with SEAL before the Walrus upload + on-chain registration. Waldrop never sees plaintext after encryption is enabled.
The six connectors
AWS S3 READY
Long-lived access key + secret. IAM user scoped to your bucket.
Google Cloud Storage READY
Short-lived OAuth access token (~1h) or service account.
Azure Blob Storage READY
Shared Access Signature (SAS) token with read-only scope.
SFTP / SSH READY
Password or OpenSSH private key. SSRF-blocked private ranges.
Dropbox READY
Google Drive READY
1 · AWS S3
S3 uses a long-lived access key ID + secret access key pair scoped to an IAM user with read access to your bucket.

Step-by-step
Open AWS IAM Console→
Users → Create user. Name it waldrop-reader. Do not tick
"Provide user access to the AWS Management Console" — programmatic-only.
Click the user → Security credentials → Create access key → choose
"Application running outside AWS". Copy both the Access key ID (starts
with AKIA) and Secret access key (shown once — save it
now).
Easy mode: attach AWS-managed AmazonS3ReadOnlyAccess
(every bucket the account owns). Tight mode: bucket-scoped inline policy —
snippet below.
Bucket-scoped IAM policy (recommended for production)
Wizard fields
| Field | What to paste |
|---|---|
Bucket * | Your bucket name (e.g. my-data-bucket) |
Region * | The bucket's AWS region (e.g. us-east-1, eu-west-2) |
Access Key ID * | From step 2, starts with AKIA |
Secret Access Key * | From step 2, the long random string |
AWS shows the secret access key only once at creation. If you lose it, delete the key and create a new one — there's no recovery.
2 · Google Cloud Storage
GCS uses a short-lived OAuth 2.0 access token (starts with
ya29.). Tokens expire after ~1 hour — generate a fresh one each
session, or use a service account for headless flows.

Option A — gcloud CLI FASTEST
Copy the output starting with ya29. and paste into the wizard.
Option B — OAuth Playground NO INSTALL
Left panel → Cloud Storage API v1 → tick
https://www.googleapis.com/auth/devstorage.read_only.
Click "Authorize APIs" → sign in with the Google account that has bucket access → click "Exchange authorization code for tokens".
From the response panel, copy the access_token field and
paste into the wizard.
Option C — Service Account FLEXIBLE
Best when no human Google account has bucket access, or for headless / CI use.
Click the new SA → Keys tab → Add Key → Create new key → JSON. Browser
downloads a .json file. Save it — Google only shows the
private key once.
Cloud Storage → Buckets → your bucket → Permissions → Grant access. Paste
the SA's email (from JSON's client_email) → role: Storage
Object Viewer.
gcloud auth activate-service-account --key-file=path/to/key.json
gcloud auth print-access-tokenWizard fields
| Field | What to paste |
|---|---|
GCS Bucket * | Your bucket name |
Access Token * | The ya29.… string from any option above |
The account / SA must have storage.objects.list + storage.objects.get on
the bucket. The Storage Object Viewer role grants both.
3 · Azure Blob Storage
Azure uses a Shared Access Signature (SAS) token — a query-string signature with embedded permissions and expiry. Generated in the Azure Portal.

Step-by-step
Allowed services: Blob only. Resource types:
Service, Container, Object.
Permissions: Read + List only (no Write /
Delete). Expiry: short window — 24 hours for one-off uploads. Protocol:
HTTPS only.
Click "Generate SAS and connection string". Copy the SAS token value —
starts with ?sv=…. Include the leading
?.
Wizard fields
| Field | What to paste |
|---|---|
Storage Account * | The account name (e.g. mywaldropstorage) |
Container * | The container name (e.g. uploads) |
SAS Token * | The ?sv=… string including the leading ? |
The SAS token must start with ?. If you copied without it, prepend it
manually before pasting.
4 · SFTP / SSH
SFTP connects over SSH (port 22 by default). Two auth methods: password or OpenSSH private key.

What you'll need from your server admin
| Field | What it is |
|---|---|
Host * | Server's hostname or IP (e.g. sftp.example.com) |
Port | Default 22; some servers use 2222 |
Username * | Your SFTP account |
Auth method | Password OR Private key |
Password | If using password auth |
Private key | OpenSSH-format key — starts with -----BEGIN OPENSSH PRIVATE KEY----- |
Path | Directory or file path (e.g. /uploads/data) |
Generating an OpenSSH key (if you don't have one)
SFTP files are capped at 25 MB because the server-action transport uses base64 (response size budget). For larger SFTP files, request a streaming route handler.
Waldrop blocks SFTP connections to loopback (127.0.0.1, localhost) and
RFC1918 private ranges (10.*, 192.168.*, 172.16-31.*). Use a public
hostname.
5 · Dropbox
Dropbox supports two flavors: OAuth (real user sign-in, what you'd ship to production) and paste-token (developer / testing).

One-time app setup (required for both flavors)
Dropbox App Console → Create app. API: "Scoped access". Access: "Full Dropbox" or "App folder" (pick Full Dropbox for testing). Name: unique.
Permissions tab → tick files.metadata.read + files.content.read →
Click Submit at the bottom. Without submit, your scope changes don't
apply.
Settings tab → OAuth 2 → Redirect URIs → add:
http://localhost:3000/api/auth/dropbox/callbackFor production, also add your production callback URL.
Flavor A — OAuth flow RECOMMENDED
For real users to sign in with their own Dropbox account.
In Settings, copy the App key. Click "Show" next to App secret and copy that too.
Add to waldrop_app/.env.local:
DROPBOX_APP_KEY=your-app-key
DROPBOX_APP_SECRET=your-app-secret
DROPBOX_REDIRECT_URI=http://localhost:3000/api/auth/dropbox/callbackbun devNext.js only loads .env.local at startup.
Wizard → Dropbox → Connect Dropbox →. Approve on Dropbox. Back in the wizard you'll see a green "Connected ✓" banner. Click List Files.
Only your account and accounts you explicitly add as "Development users" can OAuth in. To allow any user, apply for "Production" status in the app's Status section (Dropbox reviews this).
Flavor B — Paste-token TESTING ONLY
Skip the env-var setup. The token is tied to your account only.
Scroll to OAuth 2 → Generated access token → click Generate. Token
starts with sl.B…. Copy it.
Wizard → Dropbox → ignore the Connect button → paste into "Or paste an access token" → click List Files.
The Path field for Dropbox uploads is set automatically from the file picker. Files in your Dropbox root list at the top; folder navigation is on the roadmap.
6 · Google Drive
Google Drive supports the same two flavors as Dropbox: OAuth (user sign-in) or service account JSON (server-side, no user interaction).

Flavor A — OAuth flow RECOMMENDED
One-time app setup
Sidebar → APIs & Services → Library → search "Google Drive API" → click → Enable.
Branding: app name + emails — save. Audience: User Type = External; Status stays "Testing"; add your Gmail to "Test users" (or OAuth blocks you). Data Access: optional — Google asks the user inline if you skip.
Auth Platform → Clients → Create client. Application type: Web application. Authorized redirect URIs:
http://localhost:3000/api/auth/gdrive/callbackCopy the Client ID and Client secret from the modal.
Add to waldrop_app/.env.local:
GDRIVE_CLIENT_ID=your-client-id
GDRIVE_CLIENT_SECRET=your-client-secret
GDRIVE_REDIRECT_URI=http://localhost:3000/api/auth/gdrive/callbackRestart bun dev.
Wizard → Google Drive → Sign in with Google →. Approve Drive read access. "Connected ✓" → List Files → pick → upload.
While the consent screen is in "Testing", only emails listed under "Test
users" can sign in. Others get "access_denied" or "this app isn't verified".
To allow any Google user, click "Publish App" — but the drive.readonly scope
requires Google's app verification (~weeks of review, demo video required).
Flavor B — Service Account JSON NO USER SIGN-IN
Use when you don't want users to OAuth — common for shared team folders or scripted use.
GCP Console → IAM & Admin → Service Accounts
→ Create service account. Name it waldrop-drive-reader.
SA → Keys tab → Add Key → Create new key → JSON. Save the downloaded file — Google shows the private key only once.
Open the JSON, find client_email
(e.g.
waldrop-drive-reader@your-project.iam.gserviceaccount.com).
In Drive: right-click file/folder → Share → paste this email → permission:
Viewer.
Wizard → Google Drive → "Or paste a service account JSON" → paste the entire JSON contents → List Files.
Service accounts can only see files explicitly shared with them. If the SA email isn't on a file's share list, listing won't return it. Good: no expiry, no consent flow, works in dev + prod. Bad: every file/folder needs a manual share.
Common errors & fixes
| Error | Likely cause | Fix |
|---|---|---|
S3 authentication failed — check Access Key ID and Secret Access Key | Wrong/expired key, or IAM user lacks policy | Re-check both fields. Verify the IAM user has s3:ListBucket + s3:GetObject on the bucket. |
Bucket not found | Typo OR wrong region | Check bucket name. Region must match where the bucket lives — find it in S3 Console. |
GCS auth failed — provide a valid access token | Token expired (1h) or missing storage.objects.list/get | Generate fresh: gcloud auth print-access-token. For SAs, ensure Storage Object Viewer on the bucket. |
Azure auth failed — SAS token needs Read permission | SAS scoped without Read or expired | Regenerate SAS with Read + List permissions and a fresh expiry. |
SAS token must start with '?' | Pasted without the leading question mark | Prepend ? manually. Full string: ?sv=2024-…&ss=b&…. |
Dropbox not connected — sign in or paste a token | No OAuth cookie, no paste-token | Click "Connect Dropbox →" or paste a token. |
Dropbox auth failed — token expired or invalid | OAuth token expired (~4h) or revoked | Disconnect → Connect to mint a fresh token. |
Drive auth failed — token expired or insufficient permission | OAuth token expired (1h) or missing drive.readonly | Disconnect → Connect. If SA, confirm files are shared with SA email. |
OAuth state mismatch (possible CSRF) — please retry | State cookie expired (10 min) or browser dropped it | Click Connect again. Don't keep the OAuth tab open > 10 min before approving. |
Drive OAuth not configured — set GDRIVE_CLIENT_ID … | .env.local missing Drive vars, or bun dev not restarted | Add the three vars + restart. |
File too large: … bytes (max 100 MB for Milestone 2) | Source exceeds cap | Split server-side, or wait for streaming in Milestone 3. |
Privacy & security model
Each upload includes credentials in the request body; the server fetches the bytes, then forgets. No database, no log line.
Dropbox + Drive OAuth tokens live in HTTP-only cookies — not accessible to JavaScript, same-origin only.
When encryption is enabled, bytes are encrypted in your browser before reaching Walrus. The publisher (and Waldrop's server) only ever see ciphertext.
The wallet signs register_blob over the actual content hash —
verifiable, tamper-evident.
All connectors use read-only creds. Even a compromised Waldrop server could only download files you'd already shared, never modify or delete.
File size limits
| Connector | Limit (Milestone 2) | Why |
|---|---|---|
| Local files | 50 MB | Browser memory + Walrus publisher cap |
| S3 / Azure / GCS / Dropbox / GDrive | 100 MB | Server-side streaming; browser still holds for SEAL |
| SFTP | 25 MB | Server-action transport uses base64 (33% inflation) |
| URL fetch | 100 MB | Same as cloud connectors |
Streaming uploads (no full-buffer in browser) are planned for Milestone 3, which will unlock multi-gigabyte file support.