diff --git a/custom/TwoFactorsPasskeysSettings.vue b/custom/TwoFactorsPasskeysSettings.vue index 13ad133..492afb5 100644 --- a/custom/TwoFactorsPasskeysSettings.vue +++ b/custom/TwoFactorsPasskeysSettings.vue @@ -241,7 +241,23 @@ return JSON.stringify((credential as PublicKeyCredential).toJSON()); } catch (error) { console.error(t('Error creating WebAuthn credential:', error)); - adminforth.alert({ message: t('Error creating passkey.'), variant: 'warning' }); + + let message = t('Failed to create passkey.'); + + if (error?.name === 'InvalidStateError') { + message = t('A passkey for this account already exists on this device.'); + } + + if (error?.name === 'NotAllowedError') { + message = t('Passkey creation was cancelled.'); + } + + if (error?.name === 'NotSupportedError') { + message = t('Passkeys are not supported on this device or browser.'); + } + + adminforth.alert({ message, variant: 'danger'}); + return null; } } diff --git a/custom/utils.js b/custom/utils.js index 63ccf6d..997230f 100644 --- a/custom/utils.js +++ b/custom/utils.js @@ -122,7 +122,7 @@ codeError.value = t('A previous passkey attempt was still pending. Please try again.'); return null; } else if (name === 'NotAllowedError') { - adminforth.alert({ message: `The operation either timed out or was not allowed`, variant: 'warning' }); + adminforth.alert({ message: `The operation either timed out or was not allowed`, variant: 'danger' }); codeError.value = 'The operation either timed out or was not allowed.'; return null; } else { diff --git a/index.ts b/index.ts index 2fc4035..3000595 100644 --- a/index.ts +++ b/index.ts @@ -601,7 +601,8 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin { this.adminforth.auth.setAuthCookie({expireInDuration: decoded.sessionDuration, response, username:decoded.userName, pk:decoded.pk}) return { status: 'ok', allowedLogin: true } } else { - return {error: 'Verification failed'} + response.setStatus(403); + return {error: 'Wrong or expired TOTP code', } } } }