From 60de6cefed9683ecafe1206810457196f2504d08 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 21 Dec 2025 19:24:41 +0100 Subject: [PATCH] Fix WebAuthn error checking (#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 6de84e94e0..774d41dce0 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; }