From 39e83bd3fd7aa0df4658496339bce8161798ee54 Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 6 Jan 2026 05:57:59 +0100 Subject: [PATCH] Fix WebAuthn error checking (#36219) (#36235) Backport of https://github.com/go-gitea/gitea/pull/36219 Fixes: https://github.com/go-gitea/gitea/issues/36216 Now `detectWebAuthnSupport` returns the error type and lets the caller decide whether they call `webAuthnError` and show the error. It no longer shows the error during page load when the user has not even interacted with the feature. The bug affects all users on HTTP, so I think a quick fix release for this might be good. --- web_src/js/features/user-auth-webauthn.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/web_src/js/features/user-auth-webauthn.ts b/web_src/js/features/user-auth-webauthn.ts index 8a47d749cb..e8c6b5093e 100644 --- a/web_src/js/features/user-auth-webauthn.ts +++ b/web_src/js/features/user-auth-webauthn.ts @@ -4,6 +4,9 @@ import {GET, POST} from '../modules/fetch.ts'; const {appSubUrl} = window.config; +/** One of the possible values for the `data-webauthn-error-msg` attribute on the webauthn error message element */ +type ErrorType = 'general' | 'insecure' | 'browser' | 'unable-to-process' | 'duplicated' | 'unknown'; + export async function initUserAuthWebAuthn() { const elPrompt = document.querySelector('.user.signin.webauthn-prompt'); const elSignInPasskeyBtn = document.querySelector('.signin-passkey'); @@ -11,7 +14,8 @@ export async function initUserAuthWebAuthn() { return; } - if (!detectWebAuthnSupport()) { + const errorType = detectWebAuthnSupport(); + if (errorType) { if (elSignInPasskeyBtn) hideElem(elSignInPasskeyBtn); return; } @@ -177,7 +181,7 @@ async function webauthnRegistered(newCredential: any) { // TODO: Credential type window.location.reload(); } -function webAuthnError(errorType: string, message:string = '') { +function webAuthnError(errorType: ErrorType, message:string = '') { const elErrorMsg = document.querySelector(`#webauthn-error-msg`); if (errorType === 'general') { @@ -194,25 +198,26 @@ function webAuthnError(errorType: string, message:string = '') { showElem('#webauthn-error'); } -function detectWebAuthnSupport() { +/** Returns the error type or `null` when there was no error. */ +function detectWebAuthnSupport(): ErrorType | null { if (!window.isSecureContext) { - webAuthnError('insecure'); - return false; + return 'insecure'; } if (typeof window.PublicKeyCredential !== 'function') { - webAuthnError('browser'); - return false; + return 'browser'; } - return true; + return null; } export function initUserAuthWebAuthnRegister() { const elRegister = document.querySelector('#register-webauthn'); if (!elRegister) return; - if (!detectWebAuthnSupport()) { + const errorType = detectWebAuthnSupport(); + if (errorType) { + webAuthnError(errorType); elRegister.disabled = true; return; }