# Which Problems Are Solved
- Recovery codes added via `GenerateRecoveryCodes` were never listed as
active authentication methods by `ListAuthenticationMethodTypes`. The
`user_auth_method` projection reducer (`reduceInitAuthMethod`) set the
state to `MFAStateNotReady`, expecting a subsequent verification event
to transition it to `MFAStateReady`. Unlike TOTP, U2F, and Passwordless
— which all have distinct verification events — recovery codes have no
such event, so they were permanently stuck in `NotReady`.
# How the Problems Are Solved
- Introduced a dedicated `reduceAddRecoveryCodes` reducer for
`HumanRecoveryCodesAddedEvent` that sets `MFAStateReady` immediately,
since recovery codes are usable as soon as they are generated.
- Uses `NewUpsertStatement` (instead of `NewCreateStatement`) so that
regenerating recovery codes for the same user updates the existing row
rather than failing on a duplicate key conflict.
- Removed the `HumanRecoveryCodesAddedEvent` case from
`reduceInitAuthMethod`.
# Additional Changes
- Added `UserAuthMethodTypeRecoveryCode` mapping in `authMethodTypeToPb`
unit test.
- Added integration tests for `ListAuthenticationMethodTypes` covering
both the "recovery codes present" and "recovery codes removed" cases.
# Additional Context
* https://github.com/zitadel/zitadel/issues/11317
---------
Co-authored-by: Marco A. <[email protected]>
Co-authored-by: Cursor <[email protected]>
<!--
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]>
# Which Problems Are Solved
When users are removed, their auth factors stay in the projection. This
data inconsistency is visible if a removed user is recreated with the
same ID. In such a case, the login UI and the query API methods show the
removed users auth methods. This is unexpected behavior.
The old users auth methods are not usable to log in and they are not
found by the command side. This is expected behavior.
# How the Problems Are Solved
The auth factors projection reduces the user removed event by deleting
all factors.
# Additional Context
- Reported by support request
- requires backport to 2.x and 3.x
# Which Problems Are Solved
There is no option to only query auth methods related to specific
domains.
# How the Problems Are Solved
Add domain as attribute to the ListAuthenticationMethodTypes request.
# Additional Changes
OwnerRemoved column removed from the projection.
# Additional Context
Closes#8615
---------
Co-authored-by: Livio Spring <[email protected]>
This implementation increases parallel write capabilities of the eventstore.
Please have a look at the technical advisories: [05](https://zitadel.com/docs/support/advisory/a10005) and [06](https://zitadel.com/docs/support/advisory/a10006).
The implementation of eventstore.push is rewritten and stored events are migrated to a new table `eventstore.events2`.
If you are using cockroach: make sure that the database user of ZITADEL has `VIEWACTIVITY` grant. This is used to query events.
* feat: delete organizations
* feat: tests and delete all that depends on org
* fix: grpc delete description
* fix: get back reduce OrgRemovedEvent
* fix: add @muhlemmer review suggestions
* fix: new e2e for add/delete org
* feat(command): remove org
* refactor: imports, unused code, error handling
* reduce org removed in action
* add org deletion to projections
* add org removal to projections
* add org removal to projections
* org removed projection
* lint import
* projections
* fix: table names in tests
* fix: table names in tests
* logging
* add org state
* fix(domain): add Owner removed to object details
* feat(ListQuery): add with owner removed
* fix(org-delete): add bool to functions to select with owner removed
* fix(org-delete): add bools to user grants with events to determine if dependencies lost owner
* fix(org-delete): add unit tests for owner removed and org removed events
* fix(org-delete): add handling of org remove for grants and members
* fix(org-delete): correction of unit tests for owner removed
* fix(org-delete): update projections, unit tests and get functions
* fix(org-delete): add change date to authnkeys and owner removed to org metadata
* fix(org-delete): include owner removed for login names
* fix(org-delete): some column fixes in projections and build for queries with owner removed
* indexes
* fix(org-delete): include review changes
* fix(org-delete): change user projection name after merge
* fix(org-delete): include review changes for project grant where no project owner is necessary
* fix(org-delete): include auth and adminapi tables with owner removed information
* fix(org-delete): cleanup username and orgdomain uniqueconstraints when org is removed
* fix(org-delete): add permissions for org.remove
* remove unnecessary unique constraints
* fix column order in primary keys
* fix(org-delete): include review changes
* fix(org-delete): add owner removed indexes and chang setup step to create tables
* fix(org-delete): move PK order of instance_id and change added user_grant from review
* fix(org-delete): no params for prepareUserQuery
* change to step 6
* merge main
* fix(org-delete): OldUserName rename to private
* fix linting
* cleanup
* fix: remove org test
* create prerelease
* chore: delete org-delete as prerelease
Co-authored-by: Stefan Benz <[email protected]>
Co-authored-by: Livio Spring <[email protected]>
Co-authored-by: Fabi <[email protected]>
Co-authored-by: Stefan Benz <[email protected]>
* feat(instance): add remove instance event with projections cleanup
* fix(instance): corrected used id to clean up projections
* fix merge
* fix: correct unit test projection names
* fix: current sequence of lists and query for ensuring keypair based projections
Co-authored-by: Livio Spring <[email protected]>
Co-authored-by: Fabi <[email protected]>
* fix: WebAuthN when running under non default port
* fix: remove notification schema from list of views / failed events
* fix: auth method column type in user auth methods
* begin init checks for projections
* first projection checks
* debug notification providers with query fixes
* more projections and first index
* more projections
* more projections
* finish projections
* fix tests (remove db name)
* create tables in setup
* fix logging / error handling
* add tenant to views
* rename tenant to instance_id
* add instance_id to all projections
* add instance_id to all queries
* correct instance_id on projections
* add instance_id to failed_events
* use separate context for instance
* implement features projection
* implement features projection
* remove unique constraint from setup when migration failed
* add error to failed setup event
* add instance_id to primary keys
* fix IAM projection
* remove old migrations folder
* fix keysFromYAML test