Use of long random tokens as secrets to provide access to a file can provide effective security. I'd recommend 128+ bits to make it truly outside the range of randomly guessing. You could probably get away with fewer bits, especially if you rate limit IPs based on bad guesses. E.g., if you had a 64-bit or 80 bit token and a billion such files and were attacked by a botnet with a million distinct IP addresses that each could each try 10 guesses every 10 minutes -- say you banned an IP for 10 minutes after 10 incorrect attempts, it would take them about 12 days (64 bit token) or 2300 years (80-bit token) to find a single random file.
However, to do this in a secure manner you should keep some caveats in mind:
- Use HTTPS. Network eavesdroppers can see (or secretly alter) any traffic over HTTP.
- If the document has links to other webpages and a user clicks said links, the web-server at the other end will generally see a HTTP
Referer
header in the HTTP request which will provide the full URL (including any secrets; this is even if the secret is in a query parameter like https://www.google.com?q=secret ) and will still happen if the user is in private browsing mode.
- The random token probably may be stored in your computer browser's history (unless you browse in private mode and end your session).
- Some search engine gets hold of your random token and indexes it.
- The mechanism for informing the user of the key possibly leaks it to third parties. Email is potentially exchanged unencrypted and if you use an third-party email provider your secret key is accessible to administrators at that email provider. Many users also save plaintext email to their computer with an unencrypted disk (e.g., the hard drive may be removed or someone boots into a live cd to read the disk's contents) or leave the computer logged into their email account.
Issue 4 can be usually avoided by maintaining a robots.txt
and forbidding a directory.
User-Agent: *
Disallow: /private/
You can mitigate issues 2 and 3 by requiring the user to request their document by HTTP POST (over HTTPS). That is instead of clicking a link like:
<a href="https://example.com/private/LfliQdgOAkjs9H0Oi5ZZcw">File</a>
You could do something like embed the following in a HTML email:
<p> Click the button below to get your file:
<form action="https://example.com/private_file/" method="post">
<input type="hidden" name="token" value="LfliQdgOAkjs9H0Oi5ZZcw">
<input type="submit" value="Get File">
</form>
<p>Or go to https://example.com/private_file/ and cut and paste the token <pre>LfliQdgOAkjs9H0Oi5ZZcw</pre>.
This would prevent the secret from appearing in your browser history or receiving referer links (as the URL would simply be https://example.com/private_file/
).
Alternatively, you could allow links of the form https://example.com/private/LfliQdgOAkjs9H0Oi5ZZcw
, but then redirect the user to another URL when actually serving the private https://example.com/private/document
. This would prevent issue #2 with Referer headers, but still may leave the link in your browser history.