webauthn-for-webview-shells
DiscoveredEnable passkeys in WebView-shell browsers (Via, Quark, ...) via the official androidx.webkit switch — LSPosed module; targets older WebView (~124-13x) where WebAuthn is not default-enabled; fully reve
🔑 WebAuthn for WebView Shells
Enable passkeys in lightweight WebView-based browsers — via the official androidx.webkit switch, flipped from the inside.
🧠 What this actually is
Passkeys are already inside Android's system WebView. The official guideline says every host app that embeds a WebView must opt in itself:
WebSettingsCompat.setWebAuthenticationSupport(settings, WEB_AUTHENTICATION_SUPPORT_FOR_APP);
Lightweight "shell" browsers (Via, Quark, X, and dozens more) render every page through the system WebView — but none of them make this call, so navigator.credentials() never reaches the credential stack. The capability is already there; the switch is simply never flipped.
This module flips it, without touching native app code. It is a small LSPosed module that hooks WebView construction inside target browsers and applies the official integration on their behalf, backed by its own copy of androidx.webkit.
No patching of the system password manager · no network I/O · no UI injection. Revert = flip the module off in LSPosed. That's it.
✅ What you get
graph LR
A[navigator.credentials] --> B{host switch}
B -- off --> X[no passkey prompt]
B -- module --> C[WAShell hook]
C --> D[System WebView 124]
D --> E[native password manager sheet]
- Your website now realizes the phone has a platform authenticator.
- Creating and verifying passkeys goes through the native password manager (ColorOS 密码本, One UI Passcodes, Google Password Manager…)
- The module keeps gluing itself back on whenever the host re-touches its settings.
🧱 Tech stack
| Layer | What | Why |
|---|---|---|
| Hook runtime | Xposed API 93 / LSPosed | injects into the browser's own process; module off = stock behavior |
| Bridge | androidx.webkit 1.17 (WebSettingsCompat.setWebAuthenticationSupport) | the official WebView ↔ Credential-Manager integration; shipped inside the module dex |
| Target floor | Android 7.0+ (API 24), System WebView 124+ | device must already carry WebAuthn-capable WebView; module enables, never backports |
| Build | javac → d8 → aapt2 → apksigner (plain PowerShell, no Gradle) | ~350 lines total; everything reproducible from one script |
| Depends on nothing else | no network, no UI, no system writes | reversibility is the design constraint |
Why ship our own androidx.webkit? Because the shells never bundle it — the hook must supply the bridge library it is applying.
📦 Shell support
| Browser | Status |
|---|---|
Via GP (mark.via.gp 7.3.3) | ✅ tested — passkey create + verify work with the native password manager |
Via CN (mark.via) | wired & installed by default; needs nothing but your own test |
| Everything else | ⚠️ supports this mechanism (WebView ≥ 124), but not wired by default — add the package name to TARGETS in MainHook.java, rebuild, and try it out |
🕓 Compatibility: is it even needed on your device?
Maybe not — check before reporting "no effect". The module exists because WebView used to keep WebAuthn off by default unless the host opted in. Newer WebView / OS builds have started flipping that default themselves:
| Your device situation | What you'll see |
|---|---|
| Android ≤ 16, WebView ~124–13x (historical default: opt-in required) | ✅ module's sweet spot — without it, shell browsers report "no platform authenticator" |
| Android 16/17 with a recent WebView (observed: HyperOS 4.0.0.24, Android 17, WebView past 124) | ⚠️ WebView may already enable navigator.credentials for shells by default — the module becomes a no-op redundancy on those devices; passkey success there comes from the credential provider side, not this hook |
| Shell that calls the androidx switch itself | ✅ any version — module is redundant by design (that's the goal) |
Quick self-check: disable the module in LSPosed, force-stop the browser, retry passkeys. If they still work, your device no longer needs this module — nothing is broken.
Also note the provider side: on Xiaomi HyperOS 4 the default credential provider may still reject WebView-originated requests (NotReadableError); see FAQ / 中文 FAQ.
🚀 Install
- Requires: rooted device + LSPosed, Android 7.0+, system WebView 124+
- Download the APK from Releases, install it
- Enable the module in LSPosed Manager (scope is pre-filled from the manifest) and restart your browser
- Open any passkey-capable site and watch the system sheet appear
This module is fully reversible — turn it off or pm uninstall io.github.cmyfqwq.webauthnshell; everything returns to stock with no residue.
🔨 Build it yourself
No Gradle needed — a plain PowerShell script drives javac → d8 → aapt2 → apksigner from any Android SDK:
pwsh build.ps1 # → build/WebAuthn-Shell-1.0.0.apk
Want another browser? Add its package to TARGETS in
MainHook.java and rebuild.
🧭 FAQ
Is this an exploit? No. It sets a public (androidx) setting inside the target app's own process — exactly what the shell could call itself. Nothing is added to a WebView it cannot already do, and system WebView gatekeepers stay untouched.
Why not ask the browsers upstream? Please do — a 3-line change in each browser would obsolete this module, which is the ideal outcome. This module exists to close the gap until then.
☕ Credits
- Built on the official
androidx.webkitWebView–Credential-Manager bridge - Problem coverage gathered from the caniuse passkey matrix (QQ 14.9 / Baidu 13.52 unsupported) and in-app-shell breakage reported upstream, e.g. openai/codex #31204
:fox:') built by cmyfqwq · MIT · no tracking, no network, one switch
Comments
Loading…
Similar plugins
Adds a View URL page to Settings showing the running session tokenized Web address plus a stable fixed address that survives desktop restarts and is reachable from other devices on the same LAN.
★ 0
dsh plugin --profile web add dsh-web-url-viewby YV3507
Cross-platform Web UI launcher for DeepSeek Harness: webui_start/stop/status/open model tools, a /webui start|stop|status|open slash command, a Settings-page launch card, and an optional desktop short
★ 3
MIT
TypeScript
Aug 20, 2026
dsh plugin --profile web add dsh-webui-launcherMobile access gateway for the Web GUI: isolated child-process reverse proxy with a first-visit PC approval gate (admin-token auth, DNS-rebinding defense), LAN/VPN/WAN auto-detection with network-mode
★ 0
dsh plugin --profile web add dsh-mobile-accessOne-click launcher for the Web UI: a double-click Start-DSH-Web.cmd on the Windows desktop that boots dsh web and auto-opens the browser (polling until ready), plus a web_launcher model tool (install
★ 0
dsh plugin --profile web add dsh-web-launcherby donoteatme
Browser-first, LAN-only access to the current DeepSeek Harness Web UI with one-time QR pairing, revocable devices, event-driven diagnostics, and a slot-preserving mobile layout; no companion app, clou
★ 1
↓ 182/wk
MIT
TypeScript
Sep 12, 2026
dsh plugin --profile web add dsh-local-linkby sunyuhuirong
Codex-style right-edge workspace for the dsh web UI: file tree with preview tabs (Markdown/source), an embedded browser (direct/proxy iframe), and a side chat streaming from the host LLM — all as swit
★ 0
MIT
JavaScript
Sep 3, 2026
dsh plugin --profile web add fsviewer