Skip to content

feat: QR code pairing support#532

Merged
qiin2333 merged 3 commits intomasterfrom
feature/qr-code-pairing
Mar 16, 2026
Merged

feat: QR code pairing support#532
qiin2333 merged 3 commits intomasterfrom
feature/qr-code-pairing

Conversation

@qiin2333
Copy link
Copy Markdown
Collaborator

@qiin2333 qiin2333 commented Mar 16, 2026

Summary

Add QR code pairing support to Sunshine, allowing Moonlight clients to pair by scanning a QR code from the Web UI instead of manually entering a PIN.

Changes

Core QR Pairing (62025988)

  • POST /api/qr-pair endpoint generates a moonlight://pair?host=...&port=...&pin=... URL
  • Preset PIN mechanism in nvhttp: set_preset_pin() / get_preset_pin() / clear_preset_pin() with 120s auto-expiry
  • PIN consumed automatically during getservercert pairing phase
  • Web UI: QR code display with countdown timer, cancel/refresh controls
  • Vue composable useQrPair.js for state management

IP Detection & Security Hardening (6fa0c2b0)

  • LAN IP detection: resolve loopback/VPN addresses to real LAN IP
    • UDP connect trick (connect to 8.8.8.8:53, read local endpoint)
    • Windows fallback: GetAdaptersAddresses enumeration, skip tunnel/PPP adapters
    • external_ip config takes priority for WAN/port-forwarded setups
  • Security: random_device for PIN generation, 4-digit format validation, per-IP rate limiting (5 attempts/min)
  • Pairing feedback: GET /api/qr-pair returns status (active/paired/expired/inactive), frontend polls every 2s and shows success UI on completion

Misc

  • Remove non-ASCII image filenames that break CPack ZIP packaging
  • Update sunshine-control-panel submodule

@qiin2333 qiin2333 changed the title Feature/qr code pairing feat: qr code pairing Mar 16, 2026
@qiin2333 qiin2333 changed the title feat: qr code pairing feat: QR code pairing support Mar 16, 2026
Backend:
- Add preset PIN mechanism to nvhttp (set/get/clear_preset_pin)
- Auto-use preset PIN during getservercert pairing phase
- Add POST /api/qr-pair endpoint that generates random 4-digit PIN,
  sets it as preset, and returns moonlight:// URL for QR encoding

Frontend:
- Add qrcode npm dependency for client-side QR generation
- Create useQrPair.js composable (API call, QR generation, countdown)
- Add QR code pairing card to Pin.vue with generate/refresh/cancel
- Add i18n keys for en and zh locales

The QR code encodes a moonlight://pair URL containing host, port,
PIN and server name. The preset PIN expires after 120 seconds.
…back

- Resolve loopback/VPN addresses to real LAN IP via UDP connect trick
- Windows fallback: enumerate adapters via GetAdaptersAddresses, skip tunnel/PPP
- Prefer user-configured external_ip for WAN/port-forwarded setups
- Use random_device directly for secure PIN generation
- Validate PIN format (4 digits) before setting preset
- Rate limit pairing attempts per IP (5 per minute)
- Add GET /api/qr-pair status polling (active/paired/expired/inactive)
- Frontend polls every 2s, shows success UI on pairing completion
- Extract resetQrDisplay() to deduplicate QR state clearing
- Add i18n: qr_paired_success (en/zh)
- Remove #pragma comment(lib) incompatible with MinGW
@qiin2333 qiin2333 force-pushed the feature/qr-code-pairing branch from 6fa0c2b to e019624 Compare March 16, 2026 03:50
@qiin2333 qiin2333 merged commit ea1674a into master Mar 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant