From 78ff64859738d0949f8a19e2bd20a47bd1e54f1a Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 18 Sep 2026 17:32:36 +0200 Subject: [PATCH] Add web authentication support --- .../dev/hotwire/core/config/HotwireConfig.kt | 16 ++++++++++++++++ .../hotwire/core/turbo/webview/HotwireWebView.kt | 12 ++++++++++++ 2 files changed, 28 insertions(+) diff --git a/core/src/main/kotlin/dev/hotwire/core/config/HotwireConfig.kt b/core/src/main/kotlin/dev/hotwire/core/config/HotwireConfig.kt index a37aac92..8d69b294 100644 --- a/core/src/main/kotlin/dev/hotwire/core/config/HotwireConfig.kt +++ b/core/src/main/kotlin/dev/hotwire/core/config/HotwireConfig.kt @@ -52,6 +52,22 @@ class HotwireConfig internal constructor() { WebView.setWebContentsDebuggingEnabled(value) } + /** + * Enables WebAuthn (passkey) requests from every WebView instance, using the + * embedding app's identity. Disabled by default, which matches the WebView's + * own default behavior. + * + * Your app must be associated with your website through + * [Digital Asset Links](https://developers.google.com/digital-asset-links), + * otherwise the requests are rejected. Note that the WebView reports the app's + * identity as the WebAuthn origin (`android:apk-key-hash:`), so your + * server has to accept it in addition to its web origin. + * + * Requires Android System WebView 121 or later; on older versions this + * setting has no effect. + */ + var webAuthenticationEnabled = false + /** * Called whenever a new WebView instance needs to be (re)created. Provide * your own implementation and subclass [HotwireWebView] if you need diff --git a/core/src/main/kotlin/dev/hotwire/core/turbo/webview/HotwireWebView.kt b/core/src/main/kotlin/dev/hotwire/core/turbo/webview/HotwireWebView.kt index ef256d2e..cf6733f6 100644 --- a/core/src/main/kotlin/dev/hotwire/core/turbo/webview/HotwireWebView.kt +++ b/core/src/main/kotlin/dev/hotwire/core/turbo/webview/HotwireWebView.kt @@ -42,6 +42,7 @@ open class HotwireWebView @JvmOverloads constructor( settings.setSupportMultipleWindows(true) layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT) initDayNightTheming() + initWebAuthentication() } /** @@ -104,6 +105,17 @@ open class HotwireWebView @JvmOverloads constructor( return args.joinToString(",") { gson.toJson(it) } } + private fun initWebAuthentication() { + if (!Hotwire.config.webAuthenticationEnabled) return + + if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_AUTHENTICATION)) { + WebSettingsCompat.setWebAuthenticationSupport( + settings, + WebSettingsCompat.WEB_AUTHENTICATION_SUPPORT_FOR_APP + ) + } + } + @Suppress("DEPRECATION") private fun initDayNightTheming() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {