A set of Deno v2 demo applications demonstrating secure file access using WebAuthn passkeys. I created this demo to create a super simple file server with protections that allows only sysadmins to upload files.
The demo consists of two applications:
- Passkey Generator - Used for application for creating passkeys linked to specific filepaths
- File Downloader - Used for authenticating users and downloading files using passkeys
The intended usage is that File Downloader is hosted online and Passkey Generator is just a tool locally run mimicing the hosted domain to create passkeys to then be uploaded back to the hosted site.
passkey-file-server/
├── deno.json # Deno configuration and tasks
├── generate-certs.sh # Local SSL certificate generation script
├── src/
│ ├── app-generator/ # Passkey generation application
│ │ ├── index.html # Generator web interface
│ │ └── main.ts # Generator server logic
│ ├── app-download/ # File download application
│ │ ├── index.html # Downloader web interface
│ │ └── main.ts # Downloader server logic
│ └── types.ts # Shared TypeScript types
├── data/ # Generated data (created at runtime)
│ ├── passkeys/ # Stored passkey data [env PASSKEYS_PATH]
│ └── files/ # Protected files for download [env FILES_PATH]
└── certs/ # SSL certificates (generated)
- Deno v2 installed
- OpenSSL (Optional) for certificate generation
git clone https://github.com/Bug1312/passkey-file-server
cd passkey-file-serverThe application requires HTTPS for WebAuthn to work properly. You can do this yourself, but here is a script to generate local certificates:
# Generate certificates for localhost (default)
chmod +x generate-certs.sh
./generate-certs.sh
# Or specify a custom hostname
./generate-certs.sh my.domain.comDon't forget to trust the local certificate. You may need to search this online for your specific browser/OS.
Create a .env file with your configuration following the .env.example format:
# Host configuration
HOST=my.domain.com
PARTY_NAME=Your App Name
# Challenge expiration (milliseconds)
CHALLENGE_EXPIRATION=60000
# Ports
PORT_GENERATE=3001
PORT_DOWNLOAD=3000
# Paths
PASSKEYS_PATH=data/passkeys
FILES_PATH=data/files
# SSL certificates
HTTPS_CERT_FILE=certs/cert.pem
HTTPS_KEY_FILE=certs/key.pemPlace the files you want to protect in the FILES_PATH directory:
mkdir -p data/files
cp your-secret-file.pdf data/files/# Run passkey generator
deno task dev:gen
# Run file downloader
deno task dev:download- Place a file in
FILES_PATH - Navigate your web browser to the generator application
- Enter the file path
- Click "Generate Passkey" and follow your device's passkey creation process
- The passkey is now linked to your filepath relative to
FILES_PATH
- Confirm file and passkey are inside
FILES_PATHandPASSKEYS_PATHrespectively - Navigate to the downloader application
- Click "Download File"
- Authenticate using your passkey
- The file will automatically download
None of the ENV variables are actually required. The app has default values for everything. Personally I only have an ENV file containing the HOST variable.
This app is intended to be split into local (generator) and hosted (downloader).
Use generate-certs.sh to make locally-trusted certificates of a domain and edit your /etc/hosts or equivalent to route said domain to your local application.
Pull requests are welcome for fixes. This is a demo where new content is not necessary.