diff --git a/files/dfido2-lib.js b/files/dfido2-lib.js index f4a68be..491d586 100644 --- a/files/dfido2-lib.js +++ b/files/dfido2-lib.js @@ -249,17 +249,65 @@ function errMessageFido2(result){ break; case fido2LibErrCodes.timeout: rtn=getI18NErrorMessage('Fido2LibErr103:'); - break; + break; + case fido2LibErrCodes.invalid_state: + rtn=getI18NErrorMessage('Fido2LibErr105:'); + break; + case fido2LibErrCodes.not_allowed: + rtn=getI18NErrorMessage('Fido2LibErr107:'); + break; + case fido2LibErrCodes.abort: + rtn=getI18NErrorMessage('Fido2LibErr108:'); + break; + case fido2LibErrCodes.not_supported: + rtn=getI18NErrorMessage('Fido2LibErr109:'); + break; + case fido2LibErrCodes.security: + rtn=getI18NErrorMessage('Fido2LibErr110:'); + break; + case fido2LibErrCodes.network: + rtn=getI18NErrorMessage('Fido2LibErr111:'); + break; + case fido2LibErrCodes.constraint: + rtn=getI18NErrorMessage('Fido2LibErr112:'); + break; + case fido2LibErrCodes.not_readable: + rtn=getI18NErrorMessage('Fido2LibErr113:'); + break; + case fido2LibErrCodes.encoding: + rtn=getI18NErrorMessage('Fido2LibErr114:'); + break; + case fido2LibErrCodes.data_error: + rtn=getI18NErrorMessage('Fido2LibErr115:'); + break; default: rtn=result.errorMessage?result.errorMessage:getI18NErrorMessage('Fido2LibErr104:'); } }else if(result.name && "InvalidStateError" === result.name){ rtn=getI18NErrorMessage('Fido2LibErr105:'); + }else if(result.name && "NotAllowedError" === result.name){ + rtn=getI18NErrorMessage('Fido2LibErr107:'); + }else if(result.name && "AbortError" === result.name){ + rtn=getI18NErrorMessage('Fido2LibErr108:'); + }else if(result.name && "NotSupportedError" === result.name){ + rtn=getI18NErrorMessage('Fido2LibErr109:'); + }else if(result.name && "SecurityError" === result.name){ + rtn=getI18NErrorMessage('Fido2LibErr110:'); + }else if(result.name && "NetworkError" === result.name){ + rtn=getI18NErrorMessage('Fido2LibErr111:'); + }else if(result.name && "ConstraintError" === result.name){ + rtn=getI18NErrorMessage('Fido2LibErr112:'); + }else if(result.name && "NotReadableError" === result.name){ + rtn=getI18NErrorMessage('Fido2LibErr113:'); + }else if(result.name && "EncodingError" === result.name){ + rtn=getI18NErrorMessage('Fido2LibErr114:'); + }else if(result.name && "DataError" === result.name){ + rtn=getI18NErrorMessage('Fido2LibErr115:'); }else if(result.errorMessage){ const msg = getI18NErrorMessage(result.errorMessage); rtn=msg?msg:result.errorMessage; }else{ - rtn=getI18NErrorMessage(i18n_messages, 'Fido2LibErr104:'); + rtn=getI18NErrorMessage('Fido2LibErr104:'); } return rtn; @@ -268,7 +316,17 @@ function errMessageFido2(result){ const fido2LibErrCodes = { user_canceled : -101, timeout : -102, - unknown : -999 + unknown : -999, + invalid_state : -103, + not_allowed : -104, + abort : -105, + not_supported : -106, + security : -107, + network : -108, + constraint : -109, + not_readable : -110, + encoding : -111, + data_error : -112 } const errMsgs = new Map(); @@ -298,11 +356,23 @@ errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr118:', 'Signature is not errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr119:', 'No user session!'); errMsgs.get(fido2LibErrMsgLanguages.english).set('SvrErr120:', 'User has reached the device limit!'); -errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr101:', 'Your browser does not support FIDO2.'); -errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr102:', 'The user canceled.'); -errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr103:', 'The process timeout.'); -errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr104:', 'System error.'); -errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr105:', 'The same authenticator cannot be registered again.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr101:', 'Your browser does not support FIDO2/WebAuthn.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr102:', 'The operation was canceled by the user.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr103:', 'The operation timed out.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr104:', 'A system error occurred.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr105:', 'The authenticator contains credentials that are already registered with this website.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr106:', 'Another request is already in progress.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr107:', 'The operation was not allowed.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr108:', 'The operation was aborted.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr109:', 'This operation is not supported on your device.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr110:', 'A security error occurred.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr111:', 'A network error occurred.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr112:', 'The operation failed due to a constraint violation.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr113:', 'Could not read the credential.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr114:', 'The data format is invalid.'); +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr115:', 'A data error occurred.'); + +errMsgs.get(fido2LibErrMsgLanguages.english).set('Fido2LibErr106:', 'Another request is already in progress.'); errMsgs.set(fido2LibErrMsgLanguages.japanese, new Map()); errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr101:', '登録されていないエンタープライズ認証デバイス aaguid!'); @@ -324,11 +394,23 @@ errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr118:', '署名は base6 errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr119:', 'ユーザーセッションがありません!'); errMsgs.get(fido2LibErrMsgLanguages.japanese).set('SvrErr120:', 'ユーザーはデバイスの制限数に達しました!'); -errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr101:', 'お使いのブラウザは FIDO2 をサポートしていません。'); -errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr102:', 'ユーザーがキャンセルしました。'); -errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr103:', 'プロセスがタイムアウトしました。'); -errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr104:', 'システムエラー。'); -errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr105:', '同じ認証デバイスを再登録することはできません。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr101:', 'お使いのブラウザは FIDO2/WebAuthn をサポートしていません。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr102:', 'ユーザーによって操作がキャンセルされました。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr103:', '操作がタイムアウトしました。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr104:', 'システムエラーが発生しました。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr105:', 'この認証デバイスには、すでにこの网站に登録されている憑拠が含まれています。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr106:', '別のリクエストがすでに進行中です。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr107:', '操作が許可されませんでした。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr108:', '操作が中止されました。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr109:', 'この機器ではこの操作はサポートされていません。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr110:', 'セキュリティエラーが発生しました。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr111:', 'ネットワークエラーが発生しました。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr112:', '制約違反のため操作に失敗しました。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr113:', '憑拠を読み取れませんでした。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr114:', 'データ形式が無効です。'); +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr115:', 'データエラーが発生しました。'); + +errMsgs.get(fido2LibErrMsgLanguages.japanese).set('Fido2LibErr106:', '別のリクエストがすでに進行中です。'); errMsgs.set(fido2LibErrMsgLanguages.chinese_cn, new Map()); errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr101:', '未注册的企业认证器 aaguid!'); @@ -350,11 +432,23 @@ errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr118:', '签名不是 errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr119:', '未建立用户会话!'); errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('SvrErr120:', '用户已达到设备限制数!'); -errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr101:', '您的浏览器不支持FIDO2.'); -errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr102:', '用户取消了操作。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr106:', '另一个请求正在进行中。'); + +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr101:', '您的浏览器不支持FIDO2/WebAuthn。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr102:', '操作已被用户取消。'); errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr103:', '操作超时。'); -errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr104:', '系统错误。'); -errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr105:', '无法再次注册相同的认证器。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr104:', '发生系统错误。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr105:', '您的认证器包含已在此网站注册的凭据。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr106:', '另一个请求正在进行中。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr107:', '操作不被允许。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr108:', '操作已中止。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr109:', '您的设备不支持此操作。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr110:', '发生安全错误。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr111:', '发生网络错误。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr112:', '由于约束冲突,操作失败。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr113:', '无法读取凭据。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr114:', '数据格式无效。'); +errMsgs.get(fido2LibErrMsgLanguages.chinese_cn).set('Fido2LibErr115:', '发生数据错误。'); /** * @@ -498,6 +592,7 @@ async function doAttestation(username, displayName, rpId, userVerification = 'pr } catch (err) { var errRtn = {status:'failed', errorMessage: err.message}; if(err.name) errRtn.name = err.name + if(err.name && 'NotAllowedError' === err.name){ const nowtm = (new Date()).getTime() if(nowtm > process_time_limit){ @@ -505,7 +600,27 @@ async function doAttestation(username, displayName, rpId, userVerification = 'pr }else{ errRtn.errCode = fido2LibErrCodes.user_canceled } - }else errRtn.errCode = fido2LibErrCodes.unknown + } else if(err.name && 'InvalidStateError' === err.name){ + errRtn.errCode = fido2LibErrCodes.invalid_state + } else if(err.name && 'AbortError' === err.name){ + errRtn.errCode = fido2LibErrCodes.abort + } else if(err.name && 'NotSupportedError' === err.name){ + errRtn.errCode = fido2LibErrCodes.not_supported + } else if(err.name && 'SecurityError' === err.name){ + errRtn.errCode = fido2LibErrCodes.security + } else if(err.name && 'NetworkError' === err.name){ + errRtn.errCode = fido2LibErrCodes.network + } else if(err.name && 'ConstraintError' === err.name){ + errRtn.errCode = fido2LibErrCodes.constraint + } else if(err.name && 'NotReadableError' === err.name){ + errRtn.errCode = fido2LibErrCodes.not_readable + } else if(err.name && 'EncodingError' === err.name){ + errRtn.errCode = fido2LibErrCodes.encoding + } else if(err.name && 'DataError' === err.name){ + errRtn.errCode = fido2LibErrCodes.data_error + } else { + errRtn.errCode = fido2LibErrCodes.unknown + } return errRtn; } finally { @@ -616,6 +731,7 @@ async function doAssertion(username = null, rpId = null, userVerification = 'pre } catch (err) { var errRtn = {status:'failed', errorMessage: err.message}; if(err.name) errRtn.name = err.name + if(err.name && 'NotAllowedError' === err.name){ const nowtm = (new Date()).getTime() if(nowtm > process_time_limit){ @@ -623,7 +739,27 @@ async function doAssertion(username = null, rpId = null, userVerification = 'pre }else{ errRtn.errCode = fido2LibErrCodes.user_canceled } - }else errRtn.errCode = fido2LibErrCodes.unknown + } else if(err.name && 'InvalidStateError' === err.name){ + errRtn.errCode = fido2LibErrCodes.invalid_state + } else if(err.name && 'AbortError' === err.name){ + errRtn.errCode = fido2LibErrCodes.abort + } else if(err.name && 'NotSupportedError' === err.name){ + errRtn.errCode = fido2LibErrCodes.not_supported + } else if(err.name && 'SecurityError' === err.name){ + errRtn.errCode = fido2LibErrCodes.security + } else if(err.name && 'NetworkError' === err.name){ + errRtn.errCode = fido2LibErrCodes.network + } else if(err.name && 'ConstraintError' === err.name){ + errRtn.errCode = fido2LibErrCodes.constraint + } else if(err.name && 'NotReadableError' === err.name){ + errRtn.errCode = fido2LibErrCodes.not_readable + } else if(err.name && 'EncodingError' === err.name){ + errRtn.errCode = fido2LibErrCodes.encoding + } else if(err.name && 'DataError' === err.name){ + errRtn.errCode = fido2LibErrCodes.data_error + } else { + errRtn.errCode = fido2LibErrCodes.unknown + } return errRtn; } finally { diff --git a/files/fido2-ui-sdk.js b/files/fido2-ui-sdk.js index 06cec11..ccffd69 100644 --- a/files/fido2-ui-sdk.js +++ b/files/fido2-ui-sdk.js @@ -425,6 +425,318 @@ 'ru': 'Вход отменён', 'it': 'Accesso annullato' }, + 'error_invalid_state': { + 'en-US': 'The authenticator contains credentials that are already registered with this website.', + 'zh-CN': '您的认证器包含已在此网站注册的凭据。', + 'ja': 'この認証デバイスには、すでにこの网站に登録されている憑拠が含まれています。', + 'es': 'El autenticador contiene credenciales que ya están registradas en este sitio web.', + 'de': 'Der Authenticator enthält Anmeldeinformationen, die bereits auf dieser Website registriert sind.', + 'fr': 'L\'authentificateur contient des identifiants déjà enregistrés sur ce site Web.', + 'pt': 'O autenticador contém credenciais já registradas neste site.', + 'ko': '인증기에 이미 이 웹사이트에 등록된 자격 증명이 포함되어 있습니다.', + 'ru': 'Аутентификатор содержит учетные данные, уже зарегистрированные на этом веб-сайте.', + 'it': 'L\'autenticatore contiene credenziali già registrate su questo sito web.' + }, + 'error_not_allowed': { + 'en-US': 'The operation was not allowed.', + 'zh-CN': '操作不被允许。', + 'ja': '操作が許可されませんでした。', + 'es': 'La operación no fue permitida.', + 'de': 'Der Vorgang wurde nicht zugelassen.', + 'fr': 'L\'opération n\'a pas été autorisée.', + 'pt': 'A operação não foi permitida.', + 'ko': '작업이 허용되지 않았습니다.', + 'ru': 'Операция не была разрешена.', + 'it': 'L\'operazione non è stata consentita.' + }, + 'error_abort': { + 'en-US': 'The operation was aborted.', + 'zh-CN': '操作已中止。', + 'ja': '操作が中止されました。', + 'es': 'La operación fue abortada.', + 'de': 'Der Vorgang wurde abgebrochen.', + 'fr': 'L\'opération a été abandonnée.', + 'pt': 'A operação foi abortada.', + 'ko': '작업이 중단되었습니다.', + 'ru': 'Операция была прервана.', + 'it': 'L\'operazione è stata interrotta.' + }, + 'error_not_supported': { + 'en-US': 'This operation is not supported on your device.', + 'zh-CN': '您的设备不支持此操作。', + 'ja': 'この機器ではこの操作はサポートされていません。', + 'es': 'Esta operación no es compatible con su dispositivo.', + 'de': 'Dieser Vorgang wird auf Ihrem Gerät nicht unterstützt.', + 'fr': 'Cette opération n\'est pas prise en charge sur votre appareil.', + 'pt': 'Esta operação não é suportada no seu dispositivo.', + 'ko': '이 작업은 해당 장치에서 지원되지 않습니다.', + 'ru': 'Эта операция не поддерживается на вашем устройстве.', + 'it': 'Questa operazione non è supportata sul tuo dispositivo.' + }, + 'error_security': { + 'en-US': 'A security error occurred.', + 'zh-CN': '发生安全错误。', + 'ja': 'セキュリティエラーが発生しました。', + 'es': 'Ocurrió un error de seguridad.', + 'de': 'Ein Sicherheitsfehler ist aufgetreten.', + 'fr': 'Une erreur de sécurité s\'est produite.', + 'pt': 'Ocorreu um erro de segurança.', + 'ko': '보안 오류가 발생했습니다.', + 'ru': 'Произошла ошибка безопасности.', + 'it': 'Si è verificato un errore di sicurezza.' + }, + 'error_network': { + 'en-US': 'A network error occurred.', + 'zh-CN': '发生网络错误。', + 'ja': 'ネットワークエラーが発生しました。', + 'es': 'Ocurrió un error de red.', + 'de': 'Ein Netzwerkfehler ist aufgetreten.', + 'fr': 'Une erreur de réseau s\'est produite.', + 'pt': 'Ocorreu um erro de rede.', + 'ko': '네트워크 오류가 발생했습니다.', + 'ru': 'Произошла ошибка сети.', + 'it': 'Si è verificato un errore di rete.' + }, + 'error_constraint': { + 'en-US': 'The operation failed due to a constraint violation.', + 'zh-CN': '由于约束冲突,操作失败。', + 'ja': '制約違反のため操作に失敗しました。', + 'es': 'La operación falló debido a una violación de restricción.', + 'de': 'Der Vorgang ist aufgrund einer Einschränkungsverletzung fehlgeschlagen.', + 'fr': 'L\'opération a échoué en raison d\'une violation de contrainte.', + 'pt': 'A operação falhou devido a uma violação de restrição.', + 'ko': '제약 조건 위반으로 인해 작업이 실패했습니다.', + 'ru': 'Операция не удалась из-за нарушения ограничения.', + 'it': 'L\'operazione non riuscita a causa di una violazione del vincolo.' + }, + 'error_not_readable': { + 'en-US': 'Could not read the credential.', + 'zh-CN': '无法读取凭据。', + 'ja': '憑拠を読み取れませんでした。', + 'es': 'No se pudo leer la credencial.', + 'de': 'Die Anmeldeinformation konnte nicht gelesen werden.', + 'fr': 'Impossible de lire les identifiants.', + 'pt': 'Não foi possível ler a credencial.', + 'ko': '자격 증명을 읽을 수 없습니다.', + 'ru': 'Не удалось прочитать учетные данные.', + 'it': 'Impossibile leggere le credenziali.' + }, + 'error_encoding': { + 'en-US': 'The data format is invalid.', + 'zh-CN': '数据格式无效。', + 'ja': 'データ形式が無効です。', + 'es': 'El formato de datos no es válido.', + 'de': 'Das Datenformat ist ungültig.', + 'fr': 'Le format de données n\'est pas valide.', + 'pt': 'O formato de dados é inválido.', + 'ko': '데이터 형식이 잘못되었습니다.', + 'ru': 'Формат данных недействителен.', + 'it': 'Il formato dati non è valido.' + }, + 'error_data': { + 'en-US': 'A data error occurred.', + 'zh-CN': '发生数据错误。', + 'ja': 'データエラーが発生しました。', + 'es': 'Ocurrió un error de datos.', + 'de': 'Ein Datenfehler ist aufgetreten.', + 'fr': 'Une erreur de données s\'est produite.', + 'pt': 'Ocorreu um erro de dados.', + 'ko': '데이터 오류가 발생했습니다.', + 'ru': 'Произошла ошибка данных.', + 'it': 'Si è verificato un errore nei dati.' + }, + 'error_timeout': { + 'en-US': 'The operation timed out.', + 'zh-CN': '操作超时。', + 'ja': '操作がタイムアウトしました。', + 'es': 'La operación caducó.', + 'de': 'Der Vorgang ist abgelaufen.', + 'fr': 'L\'opération a expiré.', + 'pt': 'A operação expirou.', + 'ko': '작업 시간이 초과되었습니다.', + 'ru': 'Операция истекла.', + 'it': 'L\'operazione è scaduta.' + }, + 'error_system': { + 'en-US': 'A system error occurred.', + 'zh-CN': '发生系统错误。', + 'ja': 'システムエラーが発生しました。', + 'es': 'Ocurrió un error del sistema.', + 'de': 'Ein Systemfehler ist aufgetreten.', + 'fr': 'Une erreur système s\'est produite.', + 'pt': 'Ocorreu um erro do sistema.', + 'ko': '시스템 오류가 발생했습니다.', + 'ru': 'Произошла системная ошибка.', + 'it': 'Si è verificato un errore di sistema.' + }, + 'error_browser_not_supported': { + 'en-US': 'Your browser does not support FIDO2/WebAuthn.', + 'zh-CN': '您的浏览器不支持FIDO2/WebAuthn。', + 'ja': 'お使いのブラウザは FIDO2/WebAuthn をサポートしていません。', + 'es': 'Su navegador no es compatible con FIDO2/WebAuthn.', + 'de': 'Ihr Browser unterstützt FIDO2/WebAuthn nicht.', + 'fr': 'Votre navigateur ne prend pas en charge FIDO2/WebAuthn.', + 'pt': 'Seu navegador não suporta FIDO2/WebAuthn.', + 'ko': '브라우저가 FIDO2/WebAuthn을 지원하지 않습니다.', + 'ru': 'Ваш браузер не поддерживает FIDO2/WebAuthn.', + 'it': 'Il tuo browser non supporta FIDO2/WebAuthn.' + }, + 'error_fido2lib_101': { + 'en-US': 'Your browser does not support FIDO2/WebAuthn.', + 'zh-CN': '您的浏览器不支持FIDO2/WebAuthn。', + 'ja': 'お使いのブラウザは FIDO2/WebAuthn をサポートしていません。', + 'es': 'Su navegador no es compatible con FIDO2/WebAuthn.', + 'de': 'Ihr Browser unterstützt FIDO2/WebAuthn nicht.', + 'fr': 'Votre navigateur ne prend pas en charge FIDO2/WebAuthn.', + 'pt': 'Seu navegador não suporta FIDO2/WebAuthn.', + 'ko': '브라우저가 FIDO2/WebAuthn을 지원하지 않습니다.', + 'ru': 'Ваш браузер не поддерживает FIDO2/WebAuthn.', + 'it': 'Il tuo browser non supporta FIDO2/WebAuthn.' + }, + 'error_fido2lib_102': { + 'en-US': 'The operation was canceled by the user.', + 'zh-CN': '操作已被用户取消。', + 'ja': 'ユーザーによって操作がキャンセルされました。', + 'es': 'La operación fue cancelada por el usuario.', + 'de': 'Der Vorgang wurde vom Benutzer abgebrochen.', + 'fr': 'L\'opération a été annulée par l\'utilisateur.', + 'pt': 'A operação foi cancelada pelo usuário.', + 'ko': '작업이 사용자에 의해 취소되었습니다.', + 'ru': 'Операция была отменена пользователем.', + 'it': 'L\'operazione è stata annullata dall\'utente.' + }, + 'error_fido2lib_103': { + 'en-US': 'The operation timed out.', + 'zh-CN': '操作超时。', + 'ja': '操作がタイムアウトしました。', + 'es': 'La operación caducó.', + 'de': 'Der Vorgang ist abgelaufen.', + 'fr': 'L\'opération a expiré.', + 'pt': 'A operação expirou.', + 'ko': '작업 시간이 초과되었습니다.', + 'ru': 'Операция истекла.', + 'it': 'L\'operazione è scaduta.' + }, + 'error_fido2lib_105': { + 'en-US': 'The authenticator contains credentials that are already registered with this website.', + 'zh-CN': '您的认证器包含已在此网站注册的凭据。', + 'ja': 'この認証デバイスには、すでにこの网站に登録されている憑拠が含まれています。', + 'es': 'El autenticador contiene credenciales que ya están registradas en este sitio web.', + 'de': 'Der Authenticator enthält Anmeldeinformationen, die bereits auf dieser Website registriert sind.', + 'fr': 'L\'authentificateur contient des identifiants déjà enregistrés sur ce site Web.', + 'pt': 'O autenticador contém credenciais já registradas neste site.', + 'ko': '인증기에 이미 이 웹사이트에 등록된 자격 증명이 포함되어 있습니다.', + 'ru': 'Аутентификатор содержит учетные данные, уже зарегистрированные на этом веб-сайте.', + 'it': 'L\'autenticatore contiene credenziali già registrate su questo sito web.' + }, + 'error_fido2lib_106': { + 'en-US': 'Another request is already in progress.', + 'zh-CN': '另一个请求正在进行中。', + 'ja': '別のリクエストがすでに進行中です。', + 'es': 'Otra solicitud ya está en progreso.', + 'de': 'Eine andere Anfrage wird bereits verarbeitet.', + 'fr': 'Une autre demande est déjà en cours.', + 'pt': 'Outra solicitação já está em andamento.', + 'ko': '다른 요청이 이미 진행 중입니다.', + 'ru': 'Другой запрос уже выполняется.', + 'it': 'Un\'altra richiesta è già in corso.' + }, + 'error_svr_101': { + 'en-US': 'Unregistered enterprise authenticator.', + 'zh-CN': '未注册的企业认证器。', + 'ja': '登録されていないエンタープライズ認証デバイス。', + 'es': 'Autenticador empresarial no registrado.', + 'de': 'Nicht registrierter Enterprise-Authenticator.', + 'fr': 'Authentificateur d\'entreprise non enregistré.', + 'pt': 'Autenticador empresarial não registrado.', + 'ko': '등록되지 않은 엔터프라이즈 인증기.', + 'ru': 'Незарегистрированный корпоративный аутентификатор.', + 'it': 'Autenticatore aziendale non registrato.' + }, + 'error_svr_102': { + 'en-US': 'Cannot authenticate with a unique device bound key from a different device.', + 'zh-CN': '无法使用来自其他设备的唯一设备绑定密钥进行身份验证。', + 'ja': '別のデバイスからの一意のデバイスバインドキーで認証できません。', + 'es': 'No se puede autenticar con una clave de vinculación de dispositivo única desde un dispositivo diferente.', + 'de': 'Authentifizierung mit einem eindeutigen Gerätebindungsschlüssel von einem anderen Gerät nicht möglich.', + 'fr': 'Impossible de s\'authentifier avec une clé de liaison d\'appareil unique à partir d\'un autre appareil.', + 'pt': 'Não é possível autenticar com uma chave de vinculação de dispositivo exclusiva de um dispositivo diferente.', + 'ko': '다른 장치의 고유 장치 바인딩 키로 인증할 수 없습니다.', + 'ru': 'Невозможно аутентифицироваться с ключом привязки уникального устройства с другого устройства.', + 'it': 'Impossibile autenticarsi con una chiave di associazione dispositivo univoca da un dispositivo diverso.' + }, + 'error_svr_103': { + 'en-US': 'Unable to verify signature.', + 'zh-CN': '无法验证签名。', + 'ja': '署名を認証できません。', + 'es': 'No se puede verificar la firma.', + 'de': 'Signatur kann nicht verifiziert werden.', + 'fr': 'Impossible de vérifier la signature.', + 'pt': 'Não foi possível verificar a assinatura.', + 'ko': '서명을 확인할 수 없습니다.', + 'ru': 'Не удалось проверить подпись.', + 'it': 'Impossibile verificare la firma.' + }, + 'error_svr_104': { + 'en-US': 'Key not found.', + 'zh-CN': '认证Key未找到。', + 'ja': 'キーが見つかりません!', + 'es': 'Clave no encontrada.', + 'de': 'Schlüssel nicht gefunden.', + 'fr': 'Clé non trouvée.', + 'pt': 'Chave não encontrada.', + 'ko': '키를 찾을 수 없습니다.', + 'ru': 'Ключ не найден.', + 'it': 'Chiave non trovata.' + }, + 'error_svr_105': { + 'en-US': 'Username does not exist.', + 'zh-CN': '用户名不存在。', + 'ja': 'ユーザー名は存在しません!', + 'es': 'El nombre de usuario no existe.', + 'de': 'Benutzername existiert nicht.', + 'fr': 'Le nom d\'utilisateur n\'existe pas.', + 'pt': 'O nome de usuário não existe.', + 'ko': '사용자 이름이 존재하지 않습니다.', + 'ru': 'Имя пользователя не существует.', + 'it': 'Il nome utente non esiste.' + }, + 'error_svr_106': { + 'en-US': 'Unique Device ID is required.', + 'zh-CN': '需要Unique Device ID。', + 'ja': '固有のデバイスIDが必要です!', + 'es': 'Se requiere ID de dispositivo único.', + 'de': 'Eindeutige Geräte-ID erforderlich.', + 'fr': 'L\'ID d\'appareil unique est requis.', + 'pt': 'É necessário ID de dispositivo exclusivo.', + 'ko': '고유 장치 ID가 필요합니다.', + 'ru': 'Требуется уникальный идентификатор устройства.', + 'it': 'È richiesto l\'ID dispositivo univoco.' + }, + 'error_svr_120': { + 'en-US': 'User has reached the device limit.', + 'zh-CN': '用户已达到设备限制数。', + 'ja': 'ユーザーはデバイスの制限数に達しました!', + 'es': 'El usuario ha alcanzado el límite de dispositivos.', + 'de': 'Benutzer hat das Gerätelimit erreicht.', + 'fr': 'L\'utilisateur a atteint la limite d\'appareils.', + 'pt': 'O usuário atingiu o limite de dispositivos.', + 'ko': '사용자가 장치 제한에 도달했습니다.', + 'ru': 'Пользователь достиг предела устройств.', + 'it': 'L\'utente ha raggiunto il limite del dispositivo.' + }, + 'error': { + 'en-US': 'An error occurred.', + 'zh-CN': '发生错误。', + 'ja': 'エラーが発生しました。', + 'es': 'Ocurrió un error.', + 'de': 'Ein Fehler ist aufgetreten.', + 'fr': 'Une erreur s\'est produite.', + 'pt': 'Ocorreu um erro.', + 'ko': '오류가 발생했습니다.', + 'ru': 'Произошла ошибка.', + 'it': 'Si è verificato un errore.' + }, 'msg_autofail_hint': { 'en-US': 'Auto login failed, please enter User ID', 'zh-CN': '自动登录失败,请输入用户ID', @@ -1105,7 +1417,7 @@ this._emit('fido2Error', { method: 'fido2', code: 'AUTH_FAILED', - message: error.message || this.i18n.getText('msg_fido2_failed'), + message: this._getWebAuthnErrorMessage(error), originalError: error }); } @@ -1133,6 +1445,37 @@ } }; + Fido2Login.prototype._getWebAuthnErrorI18nKey = function(error) { + if (!error || !error.name) return null; + + const errorNameMap = { + 'InvalidStateError': 'error_invalid_state', + 'NotAllowedError': 'error_not_allowed', + 'AbortError': 'error_abort', + 'NotSupportedError': 'error_not_supported', + 'SecurityError': 'error_security', + 'NetworkError': 'error_network', + 'ConstraintError': 'error_constraint', + 'NotReadableError': 'error_not_readable', + 'EncodingError': 'error_encoding', + 'DataError': 'error_data', + 'TimeoutError': 'error_timeout' + }; + + return errorNameMap[error.name] || null; + }; + + Fido2Login.prototype._getWebAuthnErrorMessage = function(error) { + if (!error) return this.i18n.getText('msg_fido2_failed'); + + const i18nKey = this._getWebAuthnErrorI18nKey(error); + if (i18nKey && this.i18n.getText(i18nKey)) { + return this.i18n.getText(i18nKey); + } + + return error.message || this.i18n.getText('msg_fido2_failed'); + }; + Fido2Login.prototype._debugLog = function() { const args = Array.prototype.slice.call(arguments); const message = args.map(arg => { @@ -1423,12 +1766,16 @@ try { const effectiveUserId = this.getEffectiveUserId(); if (!effectiveUserId) { - throw new Error('No user ID available. Please login first.'); + const err = new Error('No user ID available. Please login first.'); + this.eventManager.emit('error', err); + throw err; } const validation = this.validateUserId(); if (!validation.valid) { - throw new Error(validation.error); + const err = new Error(validation.error); + this.eventManager.emit('error', err); + throw err; } const result = await registerFido2(effectiveUserId, displayName || 'Device-' + effectiveUserId, this.config.rpId); @@ -1439,9 +1786,17 @@ this.eventManager.emit('deviceAdded', result); return result; } else { - throw new Error(result.errorMessage || 'Failed to add device'); + // Create error with original properties preserved + const err = new Error(result.errorMessage || 'Failed to add device'); + if (result.name) err.name = result.name; + if (result.errCode) err.errCode = result.errCode; + this.eventManager.emit('error', err); + throw err; } } catch (error) { + if (!error.name) { + error.name = 'DeviceManagerError'; + } this.eventManager.emit('error', error); throw error; } @@ -1451,12 +1806,16 @@ try { const effectiveUserId = this.getEffectiveUserId(); if (!effectiveUserId) { - throw new Error('No user ID available. Please login first.'); + const err = new Error('No user ID available. Please login first.'); + this.eventManager.emit('error', err); + throw err; } const validation = this.validateUserId(); if (!validation.valid) { - throw new Error(validation.error); + const err = new Error(validation.error); + this.eventManager.emit('error', err); + throw err; } const result = await delUserDeviceFido2(deviceId, this.config.rpId); @@ -1466,9 +1825,17 @@ this.eventManager.emit('deviceDeleted', deviceId); return result; } else { - throw new Error(result.errorMessage || 'Failed to delete device'); + // Create error with original properties preserved + const err = new Error(result.errorMessage || 'Failed to delete device'); + if (result.name) err.name = result.name; + if (result.errCode) err.errCode = result.errCode; + this.eventManager.emit('error', err); + throw err; } } catch (error) { + if (!error.name) { + error.name = 'DeviceManagerError'; + } this.eventManager.emit('error', error); throw error; } @@ -2048,6 +2415,65 @@ return manager; }; + Fido2UIManager.prototype._getI18nErrorMessage = function(error, defaultKey) { + if (!error) return this.i18n.getText(defaultKey || 'error'); + + const errorMessage = error.message || ''; + const errorName = error.name || ''; + + // Check WebAuthn DOM error name first + if (errorName && this._getWebAuthnErrorI18nKey) { + const i18nKey = this._getWebAuthnErrorI18nKey(error); + if (i18nKey && this.i18n.getText(i18nKey)) { + return this.i18n.getText(i18nKey); + } + } + + // Check for Fido2LibErr codes in error message + if (errorMessage.includes('Fido2LibErr')) { + const match = errorMessage.match(/Fido2LibErr(\d+):/); + if (match) { + const i18nKey = 'error_fido2lib_' + match[1]; + if (this.i18n.getText(i18nKey)) { + return this.i18n.getText(i18nKey); + } + } + } + + // Check for SvrErr codes in error message + if (errorMessage.includes('SvrErr')) { + const match = errorMessage.match(/SvrErr(\d+):/); + if (match) { + const i18nKey = 'error_svr_' + match[1]; + if (this.i18n.getText(i18nKey)) { + return this.i18n.getText(i18nKey); + } + } + } + + return errorMessage || this.i18n.getText(defaultKey || 'error'); + }; + + Fido2UIManager.prototype._getWebAuthnErrorI18nKey = function(error) { + if (!error || !error.name) return null; + + const errorNameMap = { + 'InvalidStateError': 'error_invalid_state', + 'NotAllowedError': 'error_not_allowed', + 'AbortError': 'error_abort', + 'NotSupportedError': 'error_not_supported', + 'SecurityError': 'error_security', + 'NetworkError': 'error_network', + 'ConstraintError': 'error_constraint', + 'NotReadableError': 'error_not_readable', + 'EncodingError': 'error_encoding', + 'DataError': 'error_data', + 'TimeoutError': 'error_timeout' + }; + + return errorNameMap[error.name] || null; + }; + Fido2UIManager.prototype._bindInternalEvents = function() { const self = this; @@ -2063,7 +2489,7 @@ alert(self.i18n.getText('msg_register_ok')); } catch (error) { console.error('Add device error:', error); - alert(error.message || self.i18n.getText('error')); + alert(self._getI18nErrorMessage(error, 'error')); } finally { if (addBtn) addBtn.disabled = false; } @@ -2077,7 +2503,7 @@ alert(self.i18n.getText('msg_deldev_ok')); } catch (error) { console.error('Delete device error:', error); - alert(error.message || self.i18n.getText('error')); + alert(self._getI18nErrorMessage(error, 'error')); } });