https://github.com/cloudmosa/authenticator
Transfer MFA secrets to Cloud Phone devices
https://github.com/cloudmosa/authenticator
authenticator javascript mfa mfa-authenticator
Last synced: 22 days ago
JSON representation
Transfer MFA secrets to Cloud Phone devices
- Host: GitHub
- URL: https://github.com/cloudmosa/authenticator
- Owner: cloudmosa
- License: apache-2.0
- Created: 2025-10-22T15:16:18.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-12-08T22:14:03.000Z (7 months ago)
- Last Synced: 2026-06-13T00:00:03.714Z (25 days ago)
- Topics: authenticator, javascript, mfa, mfa-authenticator
- Language: JavaScript
- Homepage: https://mfa.cloudphone.tech
- Size: 281 KB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# MFA Sync Service
Secure, ephemeral MFA secret key sharing service for Cloud Phone devices, with or without a camera.

## Availability & Use
1. Sign up for the [Developer Program](https://www.cloudphone.tech/developer-program)
2. Enable [Developer Mode](https://developer.cloudfone.com/docs/guides/developer-tools/#developer-mode) on your Cloud Phone device
3. Add this widget with the URL: [https://mfa.cloudphone.tech/sync.html](https://mfa.cloudphone.tech/sync.html) and [icon](./public/favicon-512x512.png)
4. Visit [https://mfa.cloudphone.tech/](https://mfa.cloudphone.tech/) on your desktop or mobile (Android or iOS) and scan or enter an MFA secret
5. Open MFA Sync on Cloud Phone and enter the PIN
## Key Uri Format
This app processes data in the Key URI format.
```text
otpauth://totp/Zoho:email@zoho.com?secret=JBSWY3DPEHPK3PXP&period=30&digits=6&algorithm=SHA1&issuer=Zoho
```
See [Key Uri Format](https://github.com/google/google-authenticator/wiki/Key-Uri-Format).
## Architecture
```text
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Phone │ │ │ │ Feature │
│ (Admin) │────────>│ VPS Server │<────────│ Phone │
│ Scan QR Code│ │ + Redis │ │ Enter PIN │
└─────────────┘ └──────────────┘ └─────────────┘
│ │ │
│ │ │
└─── Generate PIN ───────┤ │
│ │
└──── Retrieve Secret ────┘
```
## Features
- ✅ **Ephemeral Storage**: Secrets auto-delete after retrieval or expiration
- ✅ **Encrypted at Rest**: AES-256-GCM encryption in Redis
- ✅ **Rate Limited**: Protection against brute force attacks
- ✅ **T9-Friendly**: Simple numeric PIN entry for feature phones
- ✅ **QR Scanner**: Built-in camera scanning for admin interface
- ✅ **TOTP Generator**: Full authenticator app functionality in browser
- ✅ **Zero Dependencies**: Client-side uses only Web Crypto API
## Quick Start
### Local Development
```bash
# Install dependencies
npm install
# Start Redis
docker run -d -p 6379:6379 redis:7-alpine
# Start server
npm start
# Access at http://localhost:3000
```
### Docker Deployment
```bash
# Build and run with Docker Compose
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose down
```
## VPS Deployment
### Prerequisites
1. VPS with Docker installed
2. Domain name (optional, for HTTPS)
3. GitHub repository secrets configured
### GitHub Secrets Setup
Add these secrets to your GitHub repository:
```env
VPS_HOST=your.server.ip
VPS_USER=your-ssh-user
VPS_SSH_KEY=
ALLOWED_ORIGINS=https://mfa.cloudphone.tech
```
### Server Setup
```bash
# SSH into your VPS
ssh user@your-server
# Install Docker (if not installed)
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# Create deployment directory
sudo mkdir -p /opt/mfa-sync
sudo chown $USER:$USER /opt/mfa-sync
cd /opt/mfa-sync
# Clone repository
git clone https://github.com/yourusername/mfa-sync.git .
# Create docker-compose.yml
cp docker-compose.yml /opt/mfa-sync/
# Start services
docker-compose up -d
```
### SSL Certificate (Let's Encrypt)
```bash
# Install certbot
sudo apt-get update
sudo apt-get install certbot
# Generate certificate
sudo certbot certonly --standalone -d mfa.cloudphone.tech
# Copy certificates to nginx directory
sudo mkdir -p /opt/mfa-sync/ssl
sudo cp /etc/letsencrypt/live/mfa.cloudphone.tech/fullchain.pem /opt/mfa-sync/ssl/cert.pem
sudo cp /etc/letsencrypt/live/mfa.cloudphone.tech/privkey.pem /opt/mfa-sync/ssl/key.pem
sudo chown -R $USER:$USER /opt/mfa-sync/ssl
# Restart nginx
docker-compose restart nginx
```
## Usage
### 1. Admin Interface
Access from your smartphone with a camera:
```text
https://mfa.cloudphone.tech.com/
```
1. Click "📷 Scan QR Code"
2. Point camera at MFA QR code
3. Secret auto-fills, or paste manually
4. Click "Generate PIN"
5. Display shows 6-digit PIN
### 2. Feature Phone Interface (sync.html)
Access from your feature phone browser:
```text
https://mfa.cloudphone.tech/sync.html
```
1. Enter the 6-digit PIN from admin interface
2. Click "Retrieve Secret" (or press Enter)
3. Account added with live TOTP codes
4. Codes refresh every 30 seconds
## API Reference
### POST /api/store
Store an MFA secret and generate PIN.
**Request:**
```json
{
"secret": "JBSWY3DPEHPK3PXP",
"label": "GitHub",
"issuer": "GitHub",
"ttl": 300
}
```
**Response:**
```json
{
"pin": "123456",
"expiresIn": 300,
"expiresAt": "2025-10-22T10:15:00.000Z"
}
```
### POST /api/retrieve
Retrieve MFA secret with PIN (one-time use).
**Request:**
```json
{
"pin": "123456"
}
```
**Response:**
```json
{
"secret": "JBSWY3DPEHPK3PXP",
"label": "GitHub",
"issuer": "GitHub",
"type": "totp",
"algorithm": "SHA1",
"digits": 6,
"period": 30
}
```
### GET `/api/health`
Health check endpoint.
**Response:**
```json
{
"status": "healthy",
"redis": "connected"
}
```
## Security Considerations
### What This Service Does
✅ Provides secure, temporary exchange of MFA secrets
✅ Encrypts secrets at rest with AES-256-GCM
✅ Automatically deletes secrets after retrieval
✅ Rate limits to prevent brute force attacks
✅ Uses in-memory storage (Redis) with TTL
✅ One-time PIN retrieval only
### What You Should Do
⚠️ **Use HTTPS only** - Never deploy without SSL/TLS
⚠️ **Restrict ALLOWED_ORIGINS** - Limit to your domain
⚠️ **Use strong firewall rules** - Limit Redis access
⚠️ **Monitor logs** - Watch for suspicious activity
⚠️ **Keep secrets short-lived** - Use 5-10 minute TTLs
⚠️ **Use on trusted networks** - Avoid public WiFi for admin interface
### Threat Model
- ✅ Protects against: Interception, storage leaks, unauthorized access
- ⚠️ Limited protection: Network-level attacks require HTTPS
- ❌ Does not protect: Compromised admin device, malicious VPS
## Environment Variables
```bash
PORT=3000 # Server port
REDIS_URL=redis://localhost:6379 # Redis connection string
ALLOWED_ORIGINS=* # CORS origins (comma-separated)
NODE_ENV=production # Environment
PIN_TTL=120 # Pin Time to Live (TTL) in seconds
```
## Troubleshooting
### Redis Connection Failed
```bash
# Check Redis is running
docker ps | grep redis
# View Redis logs
docker-compose logs redis
# Test Redis connection
docker exec -it mfa-sync-redis-1 redis-cli ping
```
### PIN Not Found
- Check TTL hasn't expired
- Verify PIN is exactly 6-8 digits
- Ensure no spaces in PIN entry
- Check if already retrieved (`/api/check/:pin`)
### Camera Not Working
- Ensure HTTPS is enabled (required for camera API)
- Check browser permissions
- Try different browser (Chrome/Safari recommended)
## License
[Apache 2.0](./LICENSE)
## Contributing
Issues and pull requests welcome!