Magic links
A magic link is a long random token in a URL that grants access to exactly one package, for one recipient, until it expires.
Format
https://files.example.com/p/Yt9KxRz3M_aB7Le2Nq...
─┬─ ──────────────┬─────────
│ │
│ └── 32-byte url-safe-base64 random token
└── public route prefix
Properties
- Per-recipient — each package has its own token; cross-package guessing is infeasible
- Reusable until expiry — the recipient can come back, refresh, share with a colleague at the same recipient organization
- SHA-256-hashed in the DB — only the hash is stored; a database leak doesn't grant link access
- Revocable — owner or admin can revoke any time; revoked links return HTTP 410
- Expiring — TTL set at package creation (1–90 days), independently checked at every request
- Audited — every hit (view, download, upload, invalid attempt) recorded with IP and user-agent
Lifecycle
- Generated at package finalization (outbound) or creation (inbound)
- Sent to the recipient by email
- Recipient clicks → lands on download or upload page
- Future hits show updated
use_countandlast_used_at - At TTL or after revoke → 410 Gone on next hit
Failure responses
| Status | Meaning | Audit action |
|---|---|---|
| 410 Gone | Unknown / invalid token | token_invalid |
| 410 Gone | Past TTL | token_expired |
| 410 Gone | Manually revoked | token_revoked |
All three render the same generic "link no longer available" page to avoid leaking the exact reason to enumerators.
Security model
The token IS the auth. Anyone with the link can use it — there's no second factor. Acceptable when:
- The recipient's email account is trusted (the link gets there)
- The email transport is TLS (Gmail / Outlook / etc.)
- The HTTPS connection to your SpeedyFiles instance is TLS
If you need stronger auth (e.g. for medical/legal data), pair with:
- Short TTLs (24h, not 14 days)
- One-package-per-recipient (already the default)
- Out-of-band passcode sent via SMS or phone — track in issues if you need this
If a link leaks
- Go to the package detail page
- Click Revoke link — confirm
- All future hits return 410
- Audit log records
admin_revoke+ every prior access - (Optional) Click Delete package to remove the files from disk too