mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-07 22:55:12 +00:00
feat: Add recovery code MFA support (#9954)
<!-- Please inform yourself about the contribution guidelines on submitting a PR here: https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md#submit-a-pull-request-pr. Take note of how PR/commit titles should be written and replace the template texts in the sections below. Don't remove any of the sections. It is important that the commit history clearly shows what is changed and why. Important: By submitting a contribution you agree to the terms from our Licensing Policy as described here: https://github.com/zitadel/zitadel/blob/main/LICENSING.md#community-contributions. --> One-time recovery codes are a common multi-factor authentication (MFA) backup method, letting users access their account if they lose other MFA devices. Support for recovery codes can also reduce support burden for users locked out of their accounts and provide a more secure and reliable form of verification than security questions. # Which Problems Are Solved Zitadel currently lacks support for recovery codes. # How the Problems Are Solved This PR partially addresses recovery code support in Zitadel. Importantly, it adds recovery codes as a new 2FA `Factor` and an additional `Check` type for the Session API. ``` Example recovery code flow: 1. User generates N new recovery codes using `POST /v2/users/{user_id}/recovery_codes` 2. Zitadel hashes and stores these codes and returns the un-hashed codes in the response 3. User creates new session with an additional check: `recoveryCode` 4. Code is checked against hash and, if valid, cannot be used again 5. User attempts to adds N more codes using the same endpoint 6. If `remaining_codes + N <= RecoveryCodes->MaxCount` config value, then recovery codes are added in addition to original codes 7. User can remove all recovery codes using `DEL /v2/users/:userId/recovery_codes` ``` This PR adds: - [x] Session recovery_code check support on `POST+PATCH /v2/sessions` endpoints - [x] Adds `mfa_recovery_code_checked_at` column (default null) to `projections.sessions8` table - [x] Support for `SECOND_FACTOR_TYPE_RECOVERY_CODES` as available 2FA method on login policy - [x] Support for importing recovery codes in /import code Missing, will _not_ implement in this PR: - [ ] Admin console support for displaying Recovery Code settings for user(s) - [ ] Zitadel Typescript login support for recovery codes TODO: - [x] Additional unit and integration tests - [x] Error translations # Additional Changes None # Additional Context - Closes #6898 --------- Co-authored-by: Livio Spring <[email protected]>
This commit is contained in:
co-authored by
Livio Spring
parent
afa92e55f7
commit
5beeb5738a
@@ -159,6 +159,7 @@ export class FactorTableComponent {
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_OTP,
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_OTP_SMS,
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_OTP_EMAIL,
|
||||
SecondFactorType.SECOND_FACTOR_TYPE_RECOVERY_CODES,
|
||||
]
|
||||
: [];
|
||||
|
||||
|
||||
@@ -2396,7 +2396,8 @@
|
||||
"1": "Еднократна парола чрез приложение за удостоверяване на автентичността (TOTP)",
|
||||
"2": "Пръстов отпечатък, ключове за сигурност, Face ID и други",
|
||||
"3": "Еднократна парола по имейл (Email OTP)",
|
||||
"4": "Еднократна парола чрез SMS (SMS OTP)"
|
||||
"4": "Еднократна парола чрез SMS (SMS OTP)",
|
||||
"5": "Кодове за възстановяване"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2410,7 +2410,8 @@
|
||||
"1": "Jednorázové heslo pomocí autentizační aplikace (TOTP)",
|
||||
"2": "Otisk prstu, bezpečnostní klíče, Face ID a další",
|
||||
"3": "Jednorázové heslo e-mailem (Email OTP)",
|
||||
"4": "Jednorázové heslo SMS (SMS OTP)"
|
||||
"4": "Jednorázové heslo SMS (SMS OTP)",
|
||||
"5": "Obnovovací kódy"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2401,7 +2401,8 @@
|
||||
"1": "One Time Password per Authenticator App (TOTP)",
|
||||
"2": "Fingerabdruck, Security Keys, Face ID und andere",
|
||||
"3": "One Time Password per Email (Email OTP)",
|
||||
"4": "One Time Password per SMS (SMS OTP)"
|
||||
"4": "One Time Password per SMS (SMS OTP)",
|
||||
"5": "Wiederherstellungscodes"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2427,7 +2427,8 @@
|
||||
"1": "One Time Password by Authenticator App (TOTP)",
|
||||
"2": "Fingerprint, Security Keys, Face ID and other",
|
||||
"3": "One Time Password by Email (Email OTP)",
|
||||
"4": "One Time Password by SMS (SMS OTP)"
|
||||
"4": "One Time Password by SMS (SMS OTP)",
|
||||
"5": "Recovery Codes"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2398,7 +2398,8 @@
|
||||
"1": "One Time Password por Authenticator App (TOTP)",
|
||||
"2": "Huella dactilar, claves de seguridad, Face ID y otros",
|
||||
"3": "One Time Password por email (Email OTP)",
|
||||
"4": "One Time Password por SMS (SMS OTP)"
|
||||
"4": "One Time Password por SMS (SMS OTP)",
|
||||
"5": "Códigos de recuperación"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2402,7 +2402,8 @@
|
||||
"1": "One Time Password via une application d'authentification (TOTP)",
|
||||
"2": "Empreinte digitale, clés de sécurité, Face ID et autres",
|
||||
"3": "One Time Password par e-mail (E-mail OTP)",
|
||||
"4": "One Time Password par SMS (SMS OTP)"
|
||||
"4": "One Time Password par SMS (SMS OTP)",
|
||||
"5": "Codes de récupération"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2421,7 +2421,8 @@
|
||||
"1": "Egyszeri Jelszó az Authenticator App-al (TOTP)",
|
||||
"2": "Ujjlenyomat, Biztonsági Kulcsok, Face ID és egyéb",
|
||||
"3": "Egyszeri Jelszó Emailben (Email OTP)",
|
||||
"4": "Egyszeri jelszó SMS-ben (SMS OTP)"
|
||||
"4": "Egyszeri jelszó SMS-ben (SMS OTP)",
|
||||
"5": "Helyreállítási kódok"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2193,7 +2193,8 @@
|
||||
"1": "Kata Sandi Sekali Pakai oleh Aplikasi Authenticator (TOTP)",
|
||||
"2": "Sidik Jari, Kunci Keamanan, ID Wajah dan lainnya",
|
||||
"3": "Kata Sandi Satu Kali melalui Email (Email OTP)",
|
||||
"4": "Kata Sandi Satu Kali melalui SMS (SMS OTP)"
|
||||
"4": "Kata Sandi Satu Kali melalui SMS (SMS OTP)",
|
||||
"5": "Kode Pemulihan"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2402,7 +2402,8 @@
|
||||
"1": "One Time Password per Authenticator App (TOTP)",
|
||||
"2": "Impronta digitale, chiave di sicurezza, Face ID e altri",
|
||||
"3": "One Time Password per Email (Email OTP)",
|
||||
"4": "One Time Password per SMS (SMS OTP)"
|
||||
"4": "One Time Password per SMS (SMS OTP)",
|
||||
"5": "Codici di recupero"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2423,7 +2423,8 @@
|
||||
"1": "認証アプリ用ワンタイムパスワード(TOTP)",
|
||||
"2": "指紋、セキュリティキー、フェイスIDなど",
|
||||
"3": "Eメール用ワンタイムパスワード(email OTP)",
|
||||
"4": "SMS用ワンタイムパスワード(SMS OTP)"
|
||||
"4": "SMS用ワンタイムパスワード(SMS OTP)",
|
||||
"5": "リカバリーコード"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2423,7 +2423,8 @@
|
||||
"1": "인증 앱을 통한 일회성 비밀번호(TOTP)",
|
||||
"2": "지문, 보안 키, Face ID 및 기타",
|
||||
"3": "이메일을 통한 일회성 비밀번호(이메일 OTP)",
|
||||
"4": "SMS를 통한 일회성 비밀번호(SMS OTP)"
|
||||
"4": "SMS를 통한 일회성 비밀번호(SMS OTP)",
|
||||
"5": "복구 코드"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2398,7 +2398,8 @@
|
||||
"1": "Еднократна лозинка преку апликација за автентикатор (TOTP)",
|
||||
"2": "Отпечаток на прст, безбедносни клучеви, Face ID и други",
|
||||
"3": "Еднократна лозинка по е-пошта (Еmail OTP)",
|
||||
"4": "Еднократна лозинка преку СМС (SMS OTP)"
|
||||
"4": "Еднократна лозинка преку СМС (SMS OTP)",
|
||||
"5": "Кодови за обновување"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2420,7 +2420,8 @@
|
||||
"1": "Eenmalig wachtwoord door Authenticator App (TOTP)",
|
||||
"2": "Vingerafdruk, Beveiligingssleutels, Face ID en andere",
|
||||
"3": "Eenmalig wachtwoord per e-mail (Email OTP)",
|
||||
"4": "Eenmalig wachtwoord per SMS (SMS OTP)"
|
||||
"4": "Eenmalig wachtwoord per SMS (SMS OTP)",
|
||||
"5": "Herstelcodes"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2401,7 +2401,8 @@
|
||||
"1": "Hasło jednorazowe dla aplikacji uwierzytelniającej (TOTP)",
|
||||
"2": "Odcisk palca, Klucze Bezpieczeństwa, Face ID i inne",
|
||||
"3": "Hasło jednorazowe dla wiadomości e-mail (Email OTP)",
|
||||
"4": "Hasło jednorazowe dla wiadomości SMS (SMS OTP)"
|
||||
"4": "Hasło jednorazowe dla wiadomości SMS (SMS OTP)",
|
||||
"5": "Kody odzyskiwania"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2397,7 +2397,8 @@
|
||||
"1": "Senha de uso único para o aplicativo autenticador (TOTP)",
|
||||
"2": "Impressão digital, Chaves de Segurança, Face ID e outros",
|
||||
"3": "Senha de uso único para e-mail (Email OTP)",
|
||||
"4": "Senha de uso único para SMS (SMS OTP)"
|
||||
"4": "Senha de uso único para SMS (SMS OTP)",
|
||||
"5": "Códigos de recuperação"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2419,7 +2419,8 @@
|
||||
"1": "Parolă unică după aplicația de autentificare (TOTP)",
|
||||
"2": "Amprentă, chei de securitate, Face ID și altele",
|
||||
"3": "Parolă unică prin e-mail (OTP e-mail)",
|
||||
"4": "Parolă unică prin SMS (OTP SMS)"
|
||||
"4": "Parolă unică prin SMS (OTP SMS)",
|
||||
"5": "Coduri de recuperare"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2514,7 +2514,8 @@
|
||||
"1": "Одноразовый пароль (OTP)",
|
||||
"2": "Отпечаток пальца, ключи безопасности, Face ID и другие",
|
||||
"3": "Одноразовый пароль по электронной почте",
|
||||
"4": "Одноразовый пароль по SMS"
|
||||
"4": "Одноразовый пароль по SMS",
|
||||
"5": "Коды восстановления"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2426,7 +2426,8 @@
|
||||
"1": "Engångslösenord via autentiseringsapp (TOTP)",
|
||||
"2": "Fingeravtryck, säkerhetsnycklar, Face ID och andra",
|
||||
"3": "Engångslösenord via e-post (E-post OTP)",
|
||||
"4": "Engångslösenord via SMS (SMS OTP)"
|
||||
"4": "Engångslösenord via SMS (SMS OTP)",
|
||||
"5": "Återställningskoder"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2426,7 +2426,8 @@
|
||||
"1": "Kimlik Doğrulayıcı Uygulama ile Tek Kullanımlık Şifre (TOTP)",
|
||||
"2": "Parmak izi, Güvenlik Anahtarları, Face ID ve diğerleri",
|
||||
"3": "E-posta ile Tek Kullanımlık Şifre (Email OTP)",
|
||||
"4": "SMS ile Tek Kullanımlık Şifre (SMS OTP)"
|
||||
"4": "SMS ile Tek Kullanımlık Şifre (SMS OTP)",
|
||||
"5": "Kurtarma Kodları"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
@@ -2430,7 +2430,8 @@
|
||||
"1": "身份验证应用程序的一次性密码(TOTP)",
|
||||
"2": "指纹、安全密钥、Face ID 等",
|
||||
"3": "电子邮件一次性密码(email OTP)",
|
||||
"4": "短信一次性密码(SMS OTP)"
|
||||
"4": "短信一次性密码(SMS OTP)",
|
||||
"5": "恢复码"
|
||||
}
|
||||
},
|
||||
"LOGINPOLICY": {
|
||||
|
||||
Reference in New Issue
Block a user