Time-limited, access-controlled download URLs.
SecureDownload is a gRPC service that verifies who can access a file and mints a signed download URL that expires on your schedule — with per-user access control and a small, focused API.
$ grpcurl -plaintext -d '{"file_id":"user1_document1.pdf","user_id":"user1","expires_in_seconds":3600}' \
localhost:8080 securedownload.v1.SecureDownloadService/GetDownloadURL
{
"download_url": "<signed, time-limited URL>",
"expires_at": "<unix timestamp>"
}Features
A small, focused building block for file access.
Time-limited download URLs
GetDownloadURL issues a signed URL for a file, scoped to a user and an expiry window you set with expires_in_seconds. The response includes the URL and its expires_at timestamp.
Per-user access control
VerifyAccess checks whether a given user can reach a given file before a URL is ever minted, returning has_access and an optional reason.
gRPC API
A high-performance gRPC service — securedownload.v1.SecureDownloadService — for GetDownloadURL, VerifyAccess, and ListFiles.
File listing and metadata
ListFiles pages through the files a user can access, returning each file's name, size, content type, and created and updated timestamps.
Configurable via YAML, env, or flags
Set server, auth, and database behavior in config.yaml, override with SECUREDOWNLOAD_-prefixed environment variables, or pass command-line flags.
Structured logging and JWT auth
JSON-formatted logs at configurable levels (debug through fatal), and JWT-based auth with a signing secret you control via SECUREDOWNLOAD_AUTH_JWT_SECRET.
How it works
The lifecycle of a download URL.
- 01
Verify access
Your backend calls VerifyAccess(file_id, user_id). SecureDownload checks its per-user file permissions and returns has_access, with an optional reason when access is denied.
- 02
Mint a time-limited URL
Once access is confirmed, call GetDownloadURL(file_id, user_id, expires_in_seconds). The service returns a download_url and its expires_at unix timestamp — the expiry window is yours to set, with a configurable default_token_expiry on the server.
- 03
The client downloads before it expires
The caller hands the download_url to the end user or client. It's valid until expires_at; after that, it stops working and a fresh URL has to be minted.
- 04
List what a user can reach
Call ListFiles(user_id, page_size, page_token) to page through the files a user has access to. Each FileInfo carries file_id, name, size, content_type, created_at, and updated_at, with a next_page_token for the next page.
API
Three RPCs. That's the surface area.
SecureDownload speaks gRPC — securedownload.v1.SecureDownloadService. Here's each call against a local server with grpcurl.
GetDownloadURL
Mints a signed, time-limited download URL for a file. Returns download_url and expires_at (a unix timestamp).
grpcurl -plaintext -d '{"file_id":"user1_document1.pdf","user_id":"user1","expires_in_seconds":3600}' \
localhost:8080 securedownload.v1.SecureDownloadService/GetDownloadURLVerifyAccess
Checks whether a user can access a file. Returns has_access and an optional reason.
grpcurl -plaintext -d '{"file_id":"user1_document1.pdf","user_id":"user1"}' \
localhost:8080 securedownload.v1.SecureDownloadService/VerifyAccessListFiles
Pages through the files a user has access to. Returns files[] (file_id, name, size, content_type, created_at, updated_at) and next_page_token.
grpcurl -plaintext -d '{"user_id":"user1","page_size":10}' \
localhost:8080 securedownload.v1.SecureDownloadService/ListFilesEnterprise
Self-hosting for enterprise.
Need SecureDownload inside your own infrastructure? Self-hosting is available for enterprise deployments. It runs as a Go binary with a CLI —securedownload servestarts the gRPC server — shipped as a multi-stage Docker image (minimal, non-root, with health checks) and backed by Postgres.
$ cd securedownload
$ make docker-dev # gRPC server on :8080, Postgres on :5432, hot reload
$ make docker-prod # production imagesserver:
port: 8080
default_token_expiry: "1h"
db:
driver: postgresEvery setting in config.yaml can also be set with an environment variable prefixed SECUREDOWNLOAD_, or with command-line flags — including the JWT signing secret viaSECUREDOWNLOAD_AUTH_JWT_SECRET.