Commit Graph
2043 Commits
Author SHA1 Message Date
c9b89b97ab feat(login): Add Dutch (nl) locale (#11139)
# Which Problems Are Solved

* Missing Dutch (nl) translations in the login UI v2.

# How the Problems Are Solved

* Adds nl.json with Dutch translations.
* The same data is added to v2-default.json, because otherwise English
was overriding nl.json content.
* Adds Dutch to the language dropdown in somewhat alphabetical order.

# Additional Changes

None.

# Additional Context

None.

---------

Co-authored-by: thomas-swennenhuis <[email protected]>
2025-12-22 12:38:02 +00:00
f7aa9810ee fix(i18n): fix typos in MustBeMemoryOfOrg strings (#11085)
# Which Problems Are Solved

Strings previously were:
- The user must **be member** of the {{.OrgName}} organization.

Fixed the grammar mistake / typo and it's now:
- The user must **be a member** of the {{.OrgName}} organization.

Co-authored-by: Wim Van Laer <[email protected]>
2025-12-19 13:42:23 +00:00
8472c7683d feat(rt): authorizations (#11066)
# Which Problems Are Solved

This PR implements relational table and repository interface for the
authorizations feature as described in
https://github.com/zitadel/zitadel/issues/10767

# How the Problems Are Solved

By
* adding new `zitadel.authorizations` and `zitadel.authorization_roles`
tables
* implementing the `AuthorizationRepository` interface to create,
update, query, and delete user authorizations and roles
* implementing `authorization_relational.go` projection to update
`zitadel.authorizations` and `zitadel.authorization_roles` tables based
on events

# Additional Changes
N/A

# Additional Context
- Closes #10767

---------

Co-authored-by: Livio Spring <[email protected]>
2025-12-19 07:03:27 +01:00
Wim Van LaerandGitHub 1ce8bcbd78 fix: id token had no lifetime for client credentials (#11204)
# Which Problems Are Solved

- ID-token had no lifetime when a token was requested using the
`client_credentials` grant

# How the Problems Are Solved

- Take use the lifetime provided by the server.

# Additional Context

- Closes #11060
2025-12-17 13:39:55 +01:00
b339a3e696 feat: instance domain APIs with relational tables (#11051)
# Which Problems Are Solved

This PR implements the endpoints listed in
https://github.com/zitadel/zitadel/issues/10444 .

# How the Problems Are Solved

The implementation follows the same pattern as the Instance one. The
`Add` and `Remove` are implementing the `Commander` interface, while
`List` Domains endpoints are implementing the `Querier` interace.

The PR adds also some forgotten calls to the relational logic for the
Instance API. The commits are identifiable by the label `instance:`
prepended to them. This is the complete list: bafce01b0 , 6fe7257ab ,
e27bc9c34 , 8133ede73 , fde667953 , a3e1135ed , ee1a6f9c1

# Additional Context

- Closes #10444

---------

Co-authored-by: Elio Bischof <[email protected]>
Co-authored-by: Lebogang Phoshoko <[email protected]>
Co-authored-by: Wim Van Laer <[email protected]>
Co-authored-by: Max Peintner <[email protected]>
Co-authored-by: Gayathri Vijayan <[email protected]>
2025-12-17 12:01:09 +01:00
Livio SpringandGitHub d79bfe6eba fix(login v1): update password verification handling (#11202)
# Which Problems Are Solved

Failed password attempts in login V1 potentially created new session
entries.

# How the Problems Are Solved

Correct handling to only update existing sessions.

# Additional Changes

None

# Additional Context

- reported through support
- requires backport to v4.x
2025-12-17 09:23:54 +01:00
Tim MöhlmannandGitHub d2d85bd30e fix(email): accept SMTPUTF8 addresses (#11115)
# Which Problems Are Solved

Zitadel only accepted ASCII email addresses, while some users need to
enter internationalized addresses. For example `mö[email protected]`

# How the Problems Are Solved

- Use `net/mail` to validate email addresses, instead of a custom regex.
`net/mail` correctly accepts UTF-8 characters.
- In the management/v1 API email address validation is removed (only
string limits are applied)

# Additional Changes

- none

# Additional Context

Closes https://github.com/zitadel/zitadel/issues/9821
2025-12-11 22:59:13 +00:00
41cdc7805f feat(i18n): add Ukrainian language support (#10696)
## Summary
  - Add comprehensive Ukrainian language support to ZITADEL
  - Complete translation of all user-facing interfaces
  - Integration with existing language configuration system

  ## Changes Made
- ✅ **Console translations**: Complete Ukrainian translation for admin
console (2,861 translated strings)
- ✅ **Login interface**: Ukrainian translations for authentication flows
(535 strings)
- ✅ **Email notifications**: Ukrainian translations for system emails
(68 strings)
- ✅ **Common texts**: Ukrainian translations for success/error messages
(1,417 strings)
- ✅ **Language configuration**: Added Ukrainian to supported languages
and Angular locale registration
- ✅ **UI integration**: Added Ukrainian option to language selection
forms

  ## Translation Quality
  - Professional translations using established Ukrainian IT terminology
  - Formal language appropriate for business software
- Consistent terminology across all components (Users→Користувачі,
Organization→Організація, etc.)
  - Preserved all technical placeholders, HTML tags, and formatting

  ## Contributing Guidelines Compliance
  - ✅ Followed semantic commit message format
  - ✅ Added Ukrainian to all required configuration files
  - ✅ Maintained consistent file structure with existing languages
  - ✅ Used formal Ukrainian appropriate for business software

The Ukrainian translation is now ready for review by the ZITADEL team! 🚀

---------

Co-authored-by: Marco A. <[email protected]>
2025-12-11 15:37:31 +01:00
3903355d18 feat(settings): add secret generator type to settings RT implementation (#11152)
# Which Problems Are Solved

The `SecretGenerators` setting is missing among the instance settings in
the new relational model.

# How the Problems Are Solved

This PR adds:
* `SettingTypeSecretGenerator` type to the settings model
* `SecretGeneratorSettingsRepository` and
`secretGeneratorSettingsJSONChanges` interfaces to set, retrieve, and
delete `secret_generator` settings, and corresponding unit tests.
* projection reducers to reduce the following events:
  * `SecretGeneratorAddedEvent`
  * `SecretGeneratorChangedEvent`
  * `SecretGeneratorRemovedEvent`
* integration tests to test that the events get reduced correctly 

# Additional Changes
N/A

# Additional Context
- Part of https://github.com/zitadel/zitadel/issues/10207

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Marco A. <[email protected]>
2025-12-11 12:33:19 +01:00
826039c620 Merge commit from fork
* Force v2 permission checks on user listing

* Remove duplicated tests

* cleanup and fix tests

---------

Co-authored-by: Livio Spring <[email protected]>
2025-12-10 13:13:56 +01:00
Livio SpringandGitHub dfe064f902 fix(login): fix back button on 2fa screen to allow username change (#11125)
# Which Problems Are Solved

As reported to support, the back button on the various 2FA pages in
login V1 opened the default redirect URI, which likely started a new
auth request (e.g. from Console).

# How the Problems Are Solved

Change the back buttons to navigate to the login screen again, where a
user can change the username.
Additionally, the back button has been added to the U2F verification
screen.

# Additional Changes

None

# Additional Context

- from support
- backport to v4
2025-12-09 12:37:26 +00:00
Livio SpringandGitHub 5f3f53dca1 fix(api): add tracing interceptor on connectRPC services (#11147)
# Which Problems Are Solved

ConnectRPC based services (v2 API) was missing the root span of all
requests. Rest calls through grpc-gateway more or less worked properly.
This was due to a missing server interceptor for connectRPC services
itself. Rest call would work as the trace would start on the gateway
already.

# How the Problems Are Solved

Initiate an connectRPC OTEL interceptor and pass it to all services.

# Additional Changes

None

# Additional Context

- noticed internally
- requires backport to v4.x
2025-12-09 11:23:10 +01:00
df75be96ff Merge commit from fork
* fix: Improve host header handling and deployment mode detection

* ZITADEL_CLOUD env

* refactor service config

* service config

* cleanup

* cleanup

* util for original and public host

* instanceHost, publicHost

* cleanup constructUrl

* cleanup middleware

* add x-zitadel-forward-host as fallback for current cloud setup

* fix build

* fix: lint

* fix: update test mocks

* fix: provide basepath to unit tests

* host handling

* unit tests

* imports

* fix: getPublicHost instead of getInstanceHost

* unit tests

* update nextjs, implement jwt verify for logout_token

* pass logout information in jwt to login v2

* handle hosts in jwks url

* point idp callbacks to the api and not the login UI

* logout_hint out of logout token, typecheck

* rm unused imports

* fix oidc integration test

---------

Co-authored-by: Livio Spring <[email protected]>
2025-12-08 10:01:49 +01:00
a1bfdeb257 fix(actionsV2): executing request/response type for 'all' condition (#11071)
# Which Problems Are Solved

In actions v2, when the condition `all` is chosen, or a specific method
is not specified for a service action, the actions are not executed.

# How the Problems Are Solved

The wildcard suffix `.*` is used only for event groups. As global
`requests`, `responses` or `services with no specified method` do not
have this suffix, they were bypassing the prefix-match check. This check
therefore does not apply to action types other than `event`

This issue is fixed by removing the `e.ID == "event"` condition when
prefix-matching execution IDs to not exclude other action types
(`request`, `response`, etc).

# Additional Changes
N/A

# Additional Context

- Closes #10895

---------

Co-authored-by: Livio Spring <[email protected]>
2025-12-04 06:14:55 +00:00
b4732579cb fix(RT): correct restricting null columns (#11123)
# Which Problems Are Solved

`IS NULL` and `IS NOT NULL` conditions were incorrectly marked as
restricting columns,
and currently fails unit tests. The restricting columns are mostly used
to ensure single row selection during DELETE and UPDATE . When a `IS NOT
NULL` condition is passed, the filter may (unintentionally) apply to all
rows, while still allowing the query to execute.

Settings and other repositories (still to be done) have unified tables
for instance-level settings and organization-level settings. In those
cases the organization ID may be null or have a value. The unique
condition is a compound of multiple columns, in which case `IS NULL` is
valid as part of the other restricting columns.

# How the Problems Are Solved

In order to prevent unsafe usage of null related filters and not break
settings:

- null conditions are no longer considered restricting columns
- A function to force the restricting column state on a condition is
provided
- The settings unique condition function forces restricting column state
on the returned condition.

# Additional Changes

- add `backend/v3` to the NX build.

# Additional Context

- [pipeline
failures](https://github.com/zitadel/zitadel/actions/runs/19852295780/job/56881654340?pr=11115#step:13:3197)

---------

Co-authored-by: Elio Bischof <[email protected]>
2025-12-03 16:15:49 +00:00
FuzzbizzandGitHub 8180801641 chore(console): more natural phrasing for grant type warning message (#11111)
# Which Problems Are Solved
- The warning for redirect URIs is awkwardly phrased in the past tense.

# How the Problems Are Solved

- The present tense is used and keywords enclosed in quotation marks 
<img width="444" height="35" alt="image"
src="https://github.com/user-attachments/assets/d7593ced-d53a-4655-b34b-d1fd00d9db49"
/>


# Additional Changes
N/A

# Additional Context
N/A
2025-12-02 11:40:46 +01:00
911967c865 feat(settings_relational): adding settings table for relational db (#10769)
# Which Problems Are Solved

As part of https://github.com/zitadel/zitadel/issues/9599 to push to
move to a relational db table model, this is the migration of the
settings

# Additional Changes

I had to add 2 non source code files
`backend/v3/storage/database/events_testing/font.otf` and
`backend/v3/storage/database/events_testing/picture.png`, these are used
as part of the reduce tests, hence why they're sourced inside
`backend/v3/storage/database/events_testing/settings_instance_test.go`

- Closes https://github.com/zitadel/zitadel/issues/10207

---------

Co-authored-by: adlerhurst <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
Co-authored-by: Stefan Benz <[email protected]>
2025-12-02 08:16:21 +01:00
5beeb5738a 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]>
2025-11-24 06:44:48 +00:00
9274e008fe feat(rt): project grants (#10951)
This pull request introduces a new feature that allows adding, updating,
and querying project grants The changes are primarily in the backend and
include new database tables, repositories, and domain logic to support
project grants.

## Changes

* New `project_grants` table: A new table `zitadel.project_grants` is
introduced to store project grants It includes columns for
`instance_id`, `id`, `state`, `project_id`, `granted_org_id` and
`granting_org_id`.
* New `ProjectGrantRepository`: A new repository
`ProjectGrantRepository` is created to handle all database operations
for project grants. It provides methods to `Get`, `List`, `Create`,
`Update`, and `Delete`.
* New `project_grant_roles` table: A new table
`zitadel.project_grant_roles` is introduced to store project grant roles
It includes columns for `instance_id`, `grant_id`, `key`, `project_id`
and `project_org_id`.
* New `ProjectGrantRoleRepository`: A new repository
`ProjectGrantRoleRepository` is created to handle all database
operations for project grant roles. It provides methods to `Get`,
`List`, `Add`, and `Delete`.
* New `project_grant_relational_projection`: A new projection
`project_grant_relational_projection` is added to update the
`zitadel.project_grants` and `zitadel.project_grant_roles` tables based
on events. It handles all project grant events.
* Updated `ProjectRepository`: The `ProjectRepository` is updated to
list granted projects.

# Additional Context

Closes https://github.com/zitadel/zitadel/issues/10766

---------

Co-authored-by: Stefan Benz <[email protected]>
Co-authored-by: Marco A. <[email protected]>
Co-authored-by: Silvan <[email protected]>
2025-11-14 11:04:16 +00:00
33c51deb20 Merge commit from fork
* validate IDP linking permissions

* fix: check policy before linking

* apply suggested review comments

---------

Co-authored-by: Max Peintner <[email protected]>
2025-11-12 13:48:40 +01:00
a9846498a9 feat(group): add user groups to token claims (#11009)
# Which Problems Are Solved

If the groups of a user is requested through a scope, details related to
the user's groups are added in the token claims.

# How the Problems Are Solved
By querying the user groups that the user is a part of, and setting them
in the token claims.

This PR introduces two scopes to request user groups: `groups` and
`urn:zitadel:iam:user:groups`
* `groups` returns an array of group names in the token claims with the
same name
* `urn:zitadel:iam:user:groups` returns an array of JSON objects with
information about the user groups in the token claims with the same name

# Additional Changes

N/A

# Additional Context

- Closes #9702 
- Follow-up for PRs:
  * #10455 
  * #10853 
  * #10758 
  * #10940

---------

Co-authored-by: Livio Spring <[email protected]>
2025-11-11 09:06:45 +01:00
Livio SpringandGitHub e4a959c321 fix(authz): ignore unready auth methods for mfa requirement check (#11056)
# Which Problems Are Solved

The recent
[fix](https://github.com/zitadel/zitadel/commit/2a7db648817d95eaf6716b12345f958eecdff15d)
made sure the Zitadel API always requires MFA if a user has set up so
even though not required by the login policy. After the deployment,
multiple users reached out that also users without any MFA set up got
the corresponding `[permission_denied] mfa required (AUTHZ-KI3p0)`error.

# How the Problems Are Solved

- Only check the set up factors with are verified and ready to use.
Ignore all unready auth methods.

# Additional Changes

None

# Additional Context

- relates to
https://github.com/zitadel/zitadel/commit/2a7db648817d95eaf6716b12345f958eecdff15d
- closes https://github.com/zitadel/zitadel/issues/11055
- requires backport to v2.71.x, v3.x and v4.x
2025-11-11 05:55:59 +00:00
d7e9eddb76 fix(user): Updating user info when authenticating with external IDP (#11046)
# Which Problems Are Solved

User profile updates were not propagated when using External OIDC IDP +
Login V2

# How the Problems Are Solved

* `UpdateHumanUserRequest` is added to
`RetrieveIdentityProviderIntentResponse`
* `UpdateHumanUserRequest` is returned in the
`RetrieveIdentityProviderIntentResponse` when the user already exists
during external IDP auth, which is then used in the frontend to update
the user info

# Additional Changes

* Moved integration tests related to user intent to a separate test file
* Fix redirection after external IDP user registration

# Additional Context
- Closes #10838 
- Follow up: https://github.com/zitadel/zitadel/issues/11053

---------

Co-authored-by: Max Peintner <[email protected]>
2025-11-10 09:50:36 +01:00
SilvanandGitHub 345480faeb fix(projection): locking behavior based on configuration (#11014)
Ensure projections await running status if configured, improving
synchronization during event processing.
2025-10-31 13:10:02 +02:00
Livio SpringandGitHub b284f8474e Merge commit from fork 2025-10-29 10:12:50 +01:00
Livio SpringandGitHub b8db8cdf9c Merge commit from fork
* fix: respect lockout policy on password change (with old password)

* add tarpitting

* cleanup
2025-10-29 10:07:35 +01:00
Livio SpringandGitHub 72a5c33e6a Merge commit from fork
* fix: sanitize host headers before use

* add additional test
2025-10-29 10:05:37 +01:00
f4503e07cd feat(api): integrates drupal7 hash verifier from passwap (#10918)
# Which Problems Are Solved

- Integrates the Drupal 7 hash verifier from passwap

# Additional Changes

- The docs inform about the option to use the Drupal 7 hash verifier
- Updates passwap to version v0.10.0

# Additional Context

- Follow-up for PR
[#passwap/pull/70](https://github.com/zitadel/passwap/pull/70)

Co-authored-by: Marco A. <[email protected]>
2025-10-28 16:26:48 +00:00
Marco A.andGitHub 39a29f534a feat(domain): Instance APIs with relational tables (#10953)
# Which Problems Are Solved

This PR implements the endpoints listed in
https://github.com/zitadel/zitadel/issues/10443 .

# How the Problems Are Solved

The implementation follows the same pattern as the Organization one.
There are no peculiarities to this PR. The `Update`, `Delete` are
implementing the `Commander` interface, while `Get` and `List`
instance(s) endpoints are implementing the `Querier` interace.

# Additional Context

- Closes #10443
- Depends on #10445
2025-10-28 14:17:19 +00:00
Gayathri VijayanandGitHub ad8e8bf61f feat(group): manage users in user groups (#10940)
# Which Problems Are Solved

1. Adding users to user groups and removing users from user groups.
2. Searching for users in user groups by group IDs or user IDs

# How the Problems Are Solved

By adding:
1. The API definitions to manage users in users groups
3. The command-layer implementation of adding users/removing users
to/from user groups.
4. The projection table group_users1
5. Query-side implementation to search for users in user groups

# Additional Changes

1. Remove debug statements from unit tests.
2. Fix removal of groups when orgs are removed
3. Add unit tests for groups projection

# Additional Context

* Related to #9702 
* Follow-up for PRs 
  * https://github.com/zitadel/zitadel/pull/10455
  * https://github.com/zitadel/zitadel/pull/10758
  * https://github.com/zitadel/zitadel/pull/10853
2025-10-28 13:23:54 +00:00
Livio SpringandGitHub c2a0b9d187 feat(api): move instance service to v2 (#10919)
# Which Problems Are Solved

As part of our efforts to simplify the structure and versions of our
APIs, were moving all existing v2beta endpoints to v2 and deprecate
them. They will be removed in Zitadel V5.

# How the Problems Are Solved

- This PR moves instance v2beta service and its endpoints to a
corresponding v2 version. The v2beta service and endpoints are
deprecated.
- The docs are moved to the new GA service and its endpoints. The v2beta
is not displayed anymore.
- The comments and have been improved and, where not already done, moved
from swagger annotations to proto.
- All required fields have been marked with (google.api.field_behavior)
= REQUIRED and validation rules have been added where missing
- `Domain` has been renamed to `CustomDomain` to align with naming
conventions
- `..Query` has been renamed to `..Filter` to align with other services
- The `instance_id` parameter can now passed on all endpoints and is
properly used, but requires `system` permissions. It can be omitted to
use the own instance (identified by context as any other service).
  - The following endpoints are affected:
    - GetInstance
    - UpdateInstance
    - ListCustomDomains
    - AddTrustedDomain
    - RemoveTrustedDomain
    - ListTrustedDomains
- InstanceService has been added the InstanceInterceptor's
`explicitInstanceIdServices` to allow passing the id
- If the instance is not found by id, the error is not directly returned
to prevent enumeration.
- Permissions are checked in the API instead of the interceptor for
these calls.
- Setting the same instance name in the update no longer returns an
error, but the previous change date.
 
# Additional Changes

none

# Additional Context

- part of https://github.com/zitadel/zitadel/issues/10772
- requires backport to v4.x
2025-10-28 14:01:14 +01:00
Livio SpringandGitHub 32500e3b0c feat(api): move project service v2beta to GA (and deprecate v2beta) (#10844)
# Which Problems Are Solved

As part of our efforts to simplify the structure and versions of our
APIs, were moving all existing v2beta endpoints to v2 and deprecate
them. They will be removed in Zitadel V5.

# How the Problems Are Solved

- This PR moves project v2beta service and its endpoints to a
corresponding v2 version. The v2beta service and endpoints are
deprecated.
- The comments and have been improved and, where not already done, moved
from swagger annotations to proto.
- All required fields have been marked with `(google.api.field_behavior)
= REQUIRED` and validation rules have been added where missing.
- Name ID of the project always `project_id`
- `UpdateProjectRequest` has been updated to align with the creation and
retrieval of a project:
  - `project_role_check` has been renamed to `authorization_required`
  - `has_project_check` has been renamed to `project_access_required`
- `ListProjectRequest` has been changed:
- `project_grant_resource_owner_filter`,
`project_grant_resource_owner_filter` and
`project_organization_id_filter` have been removed and merged into a
single `organization_id_filter` where a `type` can optionally be
specified to select `owned`, `granted` or both project types within a
specified organization.
- `ListProjectGrantReques` has been changed:
- `project_resource_owner_filter` has been renamed to
`project_organization_id_filter`
- `grant_resource_owner_filter` has been renamed to
`granted_organization_id_filter`

# Additional Changes

Replaced deprecated `intergration.WithAuthorization` with
`integration.WithAuthorizationToken` in integration tests.

# Additional Context

- part of #10772 
- requires backport to v4.x
2025-10-28 12:28:45 +00:00
Livio SpringandGitHub c9ac1ce344 feat(api): move authorization service to v2 (#10914)
# Which Problems Are Solved

As part of our efforts to simplify the structure and versions of our
APIs, were moving all existing v2beta endpoints to v2 and deprecate
them. They will be removed in Zitadel V5.

# How the Problems Are Solved

- This PR moves the authorization v2beta service and its endpoints to a
corresponding v2 version. The v2beta service and endpoints are
deprecated.
- The docs are moved to the new GA service and its endpoints. The v2beta
is not displayed anymore.
- The comments and have been improved and, where not already done, moved
from swagger annotations to proto.
- All required fields have been marked with (google.api.field_behavior)
= REQUIRED and validation rules have been added where missing.
- The `organization_id` to create an authorization is now required to be
always passed. There's no implicit fallback to the project's
organization anymore.
- The `user_id` filter has been removed in favor of the recently added
`in_user_ids` filter.
- The returned `Authorization` object has been reworked to return
`project`, `organization` and `roles` as objects like the granted `user`
already was.
- Additionally the `roles` now not only contain the granted `role_keys`,
but also the `display_name` and `group`. To implement this the query has
been updated internally. Existing APIs are unchanged and still return
just the keys.

# Additional Changes

None

# Additional Context

- part of https://github.com/zitadel/zitadel/issues/10772
- closes #10746 
- requires backport to v4.x
2025-10-28 12:11:12 +00:00
196eaa84d2 fix(user): auth option while listing user metadata (#10968)
# Which Problems Are Solved

A user from `org A` with `ORG_USER_MANAGER` role in `org B` is unable to
list user metadata for a user in `org B`.

# How the Problems Are Solved

The `auth.option` is set to a specific permission (`user.read`) in the
API definition of `ListUserMetadata`, which causes the interceptors to
check for this specific permission. In this case, there is no specific
check for org membership of a user (from org A) in a target organization
(org B), and hence the call fails even though the user has the necessary
permissions.

This has been fixed by setting the `auth.option` to `authenticated`, and
the necessary [permission checks are handled in the
query-layer](https://github.com/zitadel/zitadel/blob/main/internal/query/user_metadata.go#L173).

# Additional Changes
N/A

# Additional Context
- Closes #10925

---------

Co-authored-by: Marco A. <[email protected]>
2025-10-28 11:24:50 +00:00
Gayathri VijayanandGitHub da63abd1ad fix(metrics): incorrect mapping of grpc status codes in the grpc_server_grpc_status_code_total metric (#10989)
# Which Problems Are Solved

Requests without errors were mapped being mapped to GRPC status code
`Unknown`, which were then being mapped as HTTP `500` status code.

# How the Problems Are Solved

By deriving the grpc status codes from the error only when there's an
error.
When the error is `nil`, the grpc status code is set to 0 (`OK`).

# Additional Changes

N/A

# Additional Context
- Closes #10884
2025-10-28 11:36:18 +01:00
812641ee9c chore: change prepareUserAuthMethodTypesQuery log level (#10813)
# Which Problems Are Solved

During normal operations, when listing authentication method types,
activated IDPs are added to the `userAuthMethodTypes` slice but there's
an error in the logs, causing false alarms in our alerting system which
has been configured to trigger on error-level logs:
```
{
    "logDate": "2025-09-29T07:47:49.524794306Z",
    "protocol": 0,
    "requestUrl": "/zitadel.user.v2.UserService/ListAuthenticationMethodTypes",
    "responseStatus": 0,
    "requestHeaders": {
        "authorization": [
            "[REDACTED]"
        ],
        "content-type": [
            "application/grpc+proto"
        ],
        "grpc-accept-encoding": [
            "gzip,br"
        ],
        "host": [
            "zitadel.example.com"
        ],
        "te": [
            "trailers"
        ],
        "user-agent": [
            "connect-es/2.0.4"
        ]
    },
    "responseHeaders": {},
    "instanceId": "329151080840616127",
    "projectId": "329851980840157809",
    "requestedDomain": "zitadel.example.com",
    "requestedHost": "zitadel.example.com"
}

{
    "caller": "/home/runner/work/zitadel/zitadel/internal/query/user_auth_method.go:478",
    "level": "error",
    "msg": "IDP1",
    "time": "2025-09-29T07:47:49Z"
}
```

# How the Problems Are Solved

The log was changed to debug level and the log text was updated to
better describe what is happening.

Another possible solution would be to remove the log line completely.
Reviewers can decide if this is a better solution.

# Additional Changes

None.

# Additional Context

None.

Co-authored-by: Livio Spring <[email protected]>
2025-10-24 12:09:26 +00:00
SilvanandGitHub e7b841a874 fix(assets-api): Add error handling for missing file paths (#10938) 2025-10-22 09:26:10 +00:00
f230cf0fb5 refactor(rt): add primary key columns to repo interfaces (#10843)
# Which Problems Are Solved

Relational table's primary keys are part of the SQL table definition.
However, by abstraction through the repository interfaces callers
(service layer) have no clear understanding of the primary key definion.
This might lead to confusion during implementation:

- The repository makes a sanity check on required conditions before
query execution and returns an error if the condition was not met.
- When a Get method is executed, an error is returned if not exactly one
row is found. Get replaces the legacy GetXxxByID methods we have on
projections. However, a list of flexible conditions can be passed.
- Operations like UPDATE and DELETE should often only affect a single
row, identified by the primary key. If the primary key conditions are
missing an error is returned.

Because there is no "type safety" enforced here, the errors are returned
during runtime. When all possible combinations of API arguments are not
properly tested such errors are actually bugs in the experience of the
end-user. (The API should do it's own input validation, but a
programmer's error is easily made).

# How the Problems Are Solved

Add `PrimaryKeyColumns` and `PrimaryKeyCondition` to existing repository
intefaces.

# Additional Changes

- Where reducers already used repositories, the PrimaryKeyConditions are
used where possible.

# Additional Context

- Part of
https://github.com/zitadel/zitadel/wiki/Decision-Log#expose-primary-key-definition-in-repository-interfaces

---------

Co-authored-by: Marco A. <[email protected]>
2025-10-22 08:40:21 +00:00
f04d873270 feat(domain): Organization APIs with relational tables (#10704)
# Which Problems Are Solved

This PR implements the endpoints listed in #10445 using relational
tables.

- [x] UpdateOrganization
- [x] ListOrganizations
- [x] DeleteOrganization
- [x] DeactivateOrganization
- [x] ActivateOrganization

# How the Problems Are Solved

- **UpdateOrganization:** Implemented logic for `Validate()`,
`Execute()` and `Events()`. On CQRS side, updating an organization emits
events related to the organization and its domains. Separate commanders
have been made for the domain events so that their logic is run
accordingly and we keep separation of concerns. Implementation of the
domains is left to its own ticket.

Because some domain-related data is changed during the organization
update, its original values are saved as pointers inside
[UpdateOrgCommand](https://github.com/zitadel/zitadel/blob/4f87cd8d0cfd75f290aa13c342e4939cecebef73/backend/v3/domain/org_update.go#L20).

These variables will be then used as input for the domain commanders
(that will run after the update organization one).
- **ListOrganizations:** Implemented logic for `Validate()`,
`Execute()`. Utility methods have been made to parse the input queries.
This commander is used both by the v2 and v2beta endpoint, so a
translation layer has been put in place to translate all v2beta requests
into v2. The commander strictly handles v2 request only.

The translation layer between v2beta and v2 APIs was made so to make it
simple to remove it once the v2beta APIs will be removed (a simple
deletion should suffice). A `converter` package [is
shipped](https://github.com/zitadel/zitadel/blob/4f87cd8d0cfd75f290aa13c342e4939cecebef73/backend/v3/api/org/v2/convert/README.md#L5)
as well with instruction for removal. TODOs have been put in place all
over the code to indicate that the related piece of code needs to be
removed once v2beta -> v2 transition is complete.
- **DeleteOrganization:** Implemented logic for `Validate()`,
`Execute()` and `Events()`. The `Events()` method is mostly incomplete
as it requires a lot of data that is currently not retrievable due to
the lack of their relational tables.
- **DeactivateOrganization** and **ActivateOrganization**: Implemented
logic for `Validate()`, `Execute()` and `Events()`. No notable remarks.

👉 All endpoints return matching errors to the CQRS counterpart: this way
allows re-using the integration tests and

👉 All endpoints have been unit-tested through DB mocking

👉 A bunch of TODOs have been put in place for future reworks that are
needed (e.g. `Update()` method on repository should also return a
timestamp)

# Additional Changes

- A test utility method to allow mocking query options have been made.
This was necessary because `database.QueryOption` is a function and the
only comparison possible with functions is `nil` check. So, to mock
this, `database.QueryOption` is converted first to `database.QueryOpts`.
See 2276742adaef1998ea4844e1f0dca2079e45ccfb

- A `BaseCommand` has been created with the idea to collect methods that
are going to be needed by other commands. For the moment, it only offers
a method to convert query text operations from gRPC to `domain` model.
See bb85456dd101282fa76d2e2ad165eed4c8ef61b9

- SQL operations have been reworked to allow for queries using
`ContainsIgnoreCase`, `EndsWithIgnoreCase` and other `IgnoreCase`
operations. This change is pending approval and might be reworked. See
https://github.com/zitadel/zitadel/pull/10704#discussion_r2392886177

# Additional Context

`UpdateOrganization` is partially working because the logic for handling
domain updates is not done (there is only a draft of the commanders to
showcase the call chain). See
https://github.com/zitadel/zitadel/pull/10704#discussion_r2356143178

Permissions are not implemented as they are missing. See
https://github.com/zitadel/zitadel/pull/10771

- Closes: #10445

---------

Co-authored-by: Silvan <[email protected]>
2025-10-21 15:27:38 +02:00
88213d785a fix(oidc): accept localhost redirect URIs without path nor port (#10836)
# Which Problems Are Solved

Some native OIDC applications use localhost without a path as redirect
URI. Currently, setting `http://localhost` as a redirect URI leads to a
compliance warning (`Redirect URIs must begin with your own protocol,
http://127.0.0.1, http://[::1] or http://localhost.`), while
`http://localhost/some/path` and `http://localhost:some-port` are
accepted).

# How the Problems Are Solved

This PR adds additional checks to accept `http://localhost`,
`http://127.0.0.1`, `http://[::1]` and `http://[0:0:0:0:0:0:0:1]` (their
counterpart with port and with path were already accepted).

---------

Co-authored-by: Marco Ardizzone <[email protected]>
2025-10-21 10:10:49 +00:00
Gayathri VijayanandGitHub ebc6c503a3 feat(group): add group permissions (#10853)
# Which Problems Are Solved
Ensuring the user group resource is managed with appropriate
permissions.

# How the Problems Are Solved
By configuring and checking for the relevant permissions needed to
create, read, update, and delete the user groups resource.

# Additional Changes
N/A

# Additional Context
- Related to #9702 
- Follow-up for PRs #10455,  #10758
2025-10-21 11:18:21 +02:00
Livio SpringandGitHub fda19dc85b fix(login v1): handle old sessions in logout (#10926)
# Which Problems Are Solved

Sessions created through login UI (v1) automatically get assigned an ID
after creation. This change was introduced with the OIDC back-channel
logout implementation. Sessions created before that don't have an ID and
are updated on the next (re-)authentication.
A customer now reached out, that a logout from Console was resulting in
an error. This is due to at least one session not having an ID (<null>
in sql) in the same user agent.

# How the Problems Are Solved

Since the sessionID is not used in the specific situation, we just
assign the userID as sessionID. This way all sessions are properly
terminated.

# Additional Changes

None

# Additional Context

- relates to support request
- requires backport to v4.x
2025-10-18 10:18:36 +02:00
Livio SpringandGitHub 8d5f92f80a feat(api): move organization settings endpoints to v2 (#10910)
# Which Problems Are Solved

As part of our efforts to simplify the structure and versions of our
APIs, were moving all existing v2beta endpoints to v2 and deprecate
them. They will be removed in Zitadel V5.

# How the Problems Are Solved

- This PR adds the organization settings endpoints to the settings
service v2. This was split from #10909, since that PR targets v4.x and
the corresponding feature is not yet available in v4.x, but only v5.
- The comments and have been improved and, where not already done, moved
from swagger annotations to proto.

# Additional Changes

None

# Additional Context

- relates to #10909 
- relates to #10772
2025-10-17 11:21:01 +02:00
Livio SpringandGitHub dbf877e028 fix(api): deprecate settings v2beta endpoints (#10909)
# Which Problems Are Solved

As part of our efforts to simplify the structure and versions of our
APIs, were moving all existing v2beta endpoints to v2 and deprecate
them. They will be removed in Zitadel V5.

# How the Problems Are Solved

- This PR deprecates all settings v2beta service and endpoints.
- The comments and have been improved and, where not already done, moved
from swagger annotations to proto.
- `LoginSettings`:
- `AllowUsernamePassword` has been deprecated and a corresponding
`AllowLocalAuthentication` has been introduced
- `SECOND_FACTOR_TYPE_OTP` has been deprecated and a
`SECOND_FACTOR_TYPE_TOTP` has been introduced as enum alias

# Additional Changes

- cleanups of some unused structs

# Additional Context

- part of https://github.com/zitadel/zitadel/issues/10772
- requires backport to v4.x
2025-10-17 09:02:26 +00:00
Livio SpringandGitHub 0281670030 feat(api): move application service v2beta to GA (and deprecate v2beta) (#10846)
# Which Problems Are Solved

As part of our efforts to simplify the structure and versions of our
APIs, were moving all existing v2beta endpoints to v2 and deprecate
them. They will be removed in Zitadel V5.

# How the Problems Are Solved

- This PR moves app v2beta service and its endpoints to a corresponding
to application v2 version. The v2beta service and endpoints are
deprecated.
- The comments and have been improved and, where not already done, moved
from swagger annotations to proto.
- All required fields have been marked with (google.api.field_behavior)
= REQUIRED and validation rules have been added where missing.
- Name ID of the application always `application_id`, previously was
also `id` and `app_id`.
- Get rid of all `app` abbreviations and name it `application` including
the service name, `AppState` -> `ApplicationState` and `AppSorting` ->
`ApplicationSorting`
- Updated `CreateApplicationRequest`:
- renamed `creation_request_type` to `application_type` and all its
options to `XY_configuration` instead of `XY_request`
- `RegenerateClientSecret`
  - renamed method to `GenerateClientSecret`
  - removed `app_type` from request
- `ListApplicationRequest`:
  - removed required `project_id` and provided it as a filter
- Type `ApplicationNameQuery` has been renamed to
`ApplicationNameFilter` as its usage in the request
- Renamed all fields and types from `config` to `configuration`
- Updated `DeleteApplicationKeyRequest`
  - removed `organization_id`
- Updated `GetApplicationKeyRequest`:
  - removed `project_id`, `application_id` and `organization_id``
- Updated `ListApplicationKeysRequest`:
  - removed oneOf `resource_id` and moved the options into filters
- Name ID of the application key always `key_id`.
- removed unnecessary package prefixed (`zitadel.application.v2`)
- formatted using `buf`

# Additional Changes

None

# Additional Context

- part of https://github.com/zitadel/zitadel/issues/10772
- requires backport to v4.x
2025-10-17 10:12:20 +02:00
0f2a349ec1 feat(api): move internal permission service to GA (and deprecate v2beta) (#10898)
# Which Problems Are Solved

As part of our efforts to simplify the structure and versions of our
APIs, were moving all existing v2beta endpoints to v2 and deprecate
them. They will be removed in Zitadel V5.

# How the Problems Are Solved

- This PR moves the internal permission v2beta service and its endpoints
to a corresponding v2 version. The v2beta service and endpoints are
deprecated.
- The docs are moved to the new GA service and its endpoints. The v2beta
is not displayed anymore.
- The comments and have been improved and, where not already done, moved
from swagger annotations to proto.
- All required fields have been marked with (google.api.field_behavior)
= REQUIRED and validation rules have been added where missing.
- Listing administrators of a project grant can now be done with the
`ProjectGrant` (`project_id` and `organization_id`) instead of a
`project_id`, which corresponds to creation of the administrator ship of
such grant.
- formatted using `buf`

# Additional Changes

None

# Additional Context

- part of https://github.com/zitadel/zitadel/issues/10772
- requires backport to v4.x

---------

Co-authored-by: Gayathri Vijayan <[email protected]>
2025-10-17 07:35:35 +02:00
3a91b409c4 fix(zitadel): LDAP binding error with non-ASCII characters in DN (#10578)
<!--
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.
-->

# Which Problems Are Solved

LDAP binding with non-ASCII characters in DN

# How the Problems Are Solved

The root of the problem is that ParseDN() function messes DN with
non-ASCII character. Instead of using DN object, returned from ParseDN
we use user.DN in binding request. ParseDN stays only for verifying
correctness of DN.

# Additional Context
- Closes #9970

---------

Co-authored-by: Stefan Benz <[email protected]>
2025-10-15 09:40:41 +00:00
a8bbac37d9 chore: fix some eventual consistent integration testing (#10752)
# Which Problems Are Solved

Flakiness in integration tests because of eventual consistentcy.

# How the Problems Are Solved

Split tests related to feature flags and other eventual consistent
resources.

# Additional Changes

None

# Additional Context

None

Co-authored-by: Marco A. <[email protected]>
2025-10-14 18:24:09 +02:00
Tim MöhlmannandGitHub f27ca69749 fix(query): distinct count in user list (#10840)
# Which Problems Are Solved

When listing / searching users, each user got multiplied by the amount
of metadata entries they have, towards the `total_results` count. In
PostgreSQL the `COUNT(*) OVER()` window function does not support
`DISTINCT`. Even tho the query did a distinct select, the count would
still include duplicates.

# How the Problems Are Solved

Wrap the original query in a sub-select, so that the `DISTINCT` gets
handled before the count window function is executed in the outer
function. Filters, permission and solting is applied to the inner query.
Offset, limit and count are applied to the outer query.

# Additional Changes

- none

# Additional Context

- Closes https://github.com/zitadel/zitadel/issues/10825
- Backport to 4v
2025-10-14 09:43:59 +00:00
SilvanandGitHub 6686c3b16b feat(relational): org metadata (#10761)
This pull request introduces a new feature that allows adding, updating,
and querying metadata for organizations. The changes are primarily in
the backend and include new database tables, repositories, and domain
logic to support organization metadata.

## Changes

* New `org_metadata` table: A new table `zitadel.org_metadata` is
introduced to store metadata for organizations. It includes columns for
`instance_id`, `org_id`, `key`, and `value`. The `value` is stored as a
`BYTEA` type to allow for flexible data storage.
* New `OrganizationMetadataRepository`: A new repository
`OrganizationMetadataRepository` is created to handle all database
operations for organization metadata. It provides methods to `Get`,
`List`, `Set`, and `Remove` metadata.
* New `org_metadata_relational_projection`: A new projection
`org_metadata_relational_projection` is added to update the
`zitadel.org_metadata` table based on events. It handles `MetadataSet`,
`MetadataRemoved`, and `MetadataRemovedAll` events.
* Updated `OrganizationRepository`: The `OrganizationRepository` is
updated to support loading organization metadata. A new method
`LoadMetadata` is added to enable joining the `org_metadata` table when
querying for organizations.
* Updated Organization domain: The Organization domain model is updated
to include a new field `Metadata` of type `[]*OrganizationMetadata`.

## Additional Info

* Extensible Design: The new metadata feature is designed to be
extensible, allowing for future enhancements such as indexing on
specific JSON fields within the `value` column.
* closes https://github.com/zitadel/zitadel/issues/10206
* closes https://github.com/zitadel/zitadel/issues/10214
2025-10-14 10:15:16 +01:00