feat: two-factor authentication (TOTP + backup codes)
Uses better-auth's built-in twoFactor plugin rather than hand-rolling TOTP — adds the two_factors table and users.twoFactorEnabled, wires the server/client plugins (allowPasswordless: true so OAuth-only accounts aren't locked out of managing 2FA), and adds a custom rate limit for the verify endpoints (5/min — far stricter than the default 100/10s, since a 6-digit code has a much smaller keyspace than a password). New Settings → Security section walks through enable (password confirm -> QR + backup codes -> confirm a live code before it's actually turned on, per the plugin's default flow) and disable. New /verify-2fa page handles the post-password mid-login step, with a backup-code fallback. Verified live end-to-end: enable, confirm, forced re-auth on next sign-in, TOTP accepted, backup code accepted (single-use), disable. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -583,7 +583,17 @@
|
||||
"checkInboxVerification": "Vérifiez votre boîte de réception pour l'e-mail de vérification.",
|
||||
"resendVerification": "Renvoyer l'e-mail de vérification",
|
||||
"resendingSending": "Envoi en cours…",
|
||||
"or": "ou"
|
||||
"or": "ou",
|
||||
"twoFactorTitle": "Authentification à deux facteurs",
|
||||
"twoFactorAppDescription": "Saisissez le code à 6 chiffres de votre application d'authentification.",
|
||||
"twoFactorBackupDescription": "Saisissez un de vos codes de secours.",
|
||||
"twoFactorCodeLabel": "Code",
|
||||
"twoFactorBackupCodeLabel": "Code de secours",
|
||||
"twoFactorVerify": "Vérifier",
|
||||
"twoFactorVerifying": "Vérification…",
|
||||
"twoFactorInvalidCode": "Code invalide",
|
||||
"twoFactorUseBackupCode": "Utiliser un code de secours",
|
||||
"twoFactorUseApp": "Utiliser votre application d'authentification"
|
||||
},
|
||||
"batchCooking": {
|
||||
"title": "Batch cooking",
|
||||
@@ -1162,6 +1172,31 @@
|
||||
"downloadData": "Télécharger mes données",
|
||||
"downloadDataDescription": "Obtenez un export JSON de toutes les données personnelles qu'Epicure détient sur vous — votre profil, vos recettes, votre activité et vos paramètres.",
|
||||
"downloadDataButton": "Télécharger mes données",
|
||||
"twoFactorTitle": "Authentification à deux facteurs",
|
||||
"twoFactorDescription": "Exiger un code d'une application d'authentification en plus de votre mot de passe pour vous connecter.",
|
||||
"twoFactorEnableButton": "Activer",
|
||||
"twoFactorDisableButton": "Désactiver",
|
||||
"twoFactorEnabled": "Authentification à deux facteurs activée",
|
||||
"twoFactorDisabled": "Authentification à deux facteurs désactivée",
|
||||
"twoFactorEnableFailed": "Échec du démarrage de la configuration",
|
||||
"twoFactorDisableFailed": "Échec de la désactivation",
|
||||
"twoFactorConfirmPasswordTitle": "Confirmez votre mot de passe",
|
||||
"twoFactorConfirmPasswordDescription": "Saisissez votre mot de passe pour configurer l'authentification à deux facteurs.",
|
||||
"twoFactorContinue": "Continuer",
|
||||
"twoFactorCancel": "Annuler",
|
||||
"twoFactorSetupTitle": "Configurer l'authentification à deux facteurs",
|
||||
"twoFactorSetupDescription": "Scannez ce code avec votre application d'authentification (comme Google Authenticator ou 1Password), puis saisissez le code à 6 chiffres qu'elle affiche.",
|
||||
"twoFactorQrAlt": "Code QR pour la configuration de l'authentification à deux facteurs",
|
||||
"twoFactorBackupCodesLabel": "Codes de secours",
|
||||
"twoFactorBackupCodesHint": "Conservez-les en lieu sûr — chacun ne peut être utilisé qu'une fois pour vous connecter si vous perdez l'accès à votre application d'authentification.",
|
||||
"twoFactorCopyCodes": "Copier les codes",
|
||||
"twoFactorCodesCopied": "Copié",
|
||||
"twoFactorCopyFailed": "Échec de la copie",
|
||||
"twoFactorCodeLabel": "Code à 6 chiffres",
|
||||
"twoFactorVerifyAndEnable": "Vérifier et activer",
|
||||
"twoFactorInvalidCode": "Code invalide",
|
||||
"twoFactorDisableTitle": "Désactiver l'authentification à deux facteurs",
|
||||
"twoFactorDisableDescription": "Votre compte n'aura besoin que de votre mot de passe pour vous connecter.",
|
||||
"webhookCreateFailed": "Échec de la création du webhook",
|
||||
"webhookDeleteFailed": "Échec de la suppression du webhook",
|
||||
"webhookUpdateFailed": "Échec de la mise à jour du webhook",
|
||||
|
||||
Reference in New Issue
Block a user