Commit Graph
2181 Commits
Author SHA1 Message Date
1e09b4fc19 feat(login): hu translations + I18n consistency v2 (#12447)
# Which Problems Are Solved

Fixes i18n consistency and adds HU translations for login v2

# How the Problems Are Solved

- Updated i18n files and added hu.json
- Moved all translations to v2-default.json

---------

Co-authored-by: Dobos Zoltán <[email protected]>
Co-authored-by: Liam Neville <[email protected]>
2026-07-15 11:27:25 +00:00
6eafca2872 feat: update GetActiveIdentityProviders to return Zitadel in the IdP list (#12422)
# Which Problems Are Solved

This PR extends the Settings Login API (v2 and v2beta) to include
ZITADEL IdP in the list of IdPs returned by `GetActiveIdentityProviders`

# How the Problems Are Solved

- Added `IDENTITY_PROVIDER_TYPE_ZITADEL` to Settings
IdentityProviderType enums (v2 and v2beta) and updated domain display
name handling.
- Updated Settings gRPC converters (v2 and v2beta) to map
`domain.IDPTypeZitadel` to the new proto enum value
- Added unit/integration tests


# Additional Changes
Correctly map `domain.IDPTypeApple` to
`IdentityProviderType_IDENTITY_PROVIDER_TYPE_APPLE` in v2beta instead of
unspecified.

# Additional Context
- Closes https://github.com/zitadel/zitadel/issues/12401

---------

Co-authored-by: Livio Spring <[email protected]>
2026-07-14 13:50:09 +02:00
5bdfd96be5 feat: extend DeleteProvider to include Zitadel IdP (#12396)
# Which Problems Are Solved

This PR extends `DeleteProvider` to include Zitadel provider enabling
the deletion of Zitadel IdP.

# How the Problems Are Solved

- Extend org/instance IDP remove write models to include
`ZitadelIDPAddedEvent` in event appends and queries.
- Extend command-side IDP reduction/type handling for Zitadel IDP add
events.
- Add management/admin integration tests for deleting Zitadel providers
- Add error translation key in all language locales for org-level “IDP
config not existing”.

# Additional Changes

N/A

# Additional Context.
Closes https://github.com/zitadel/zitadel/issues/12397

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: Livio Spring <[email protected]>
2026-07-13 09:22:31 +02:00
77169181a3 feat: get/list Zitadel IdP (#12394)
# Which Problems Are Solved

This PR extends the functionality of `GetProviderByID`, `ListProviders`
v1 endpoints and `GetIDPByID` v2 endpoint to also return Zitadel IdP
when queried.

# How the Problems Are Solved

- Add `PROVIDER_TYPE_ZITADEL` and a `ZitadelConfig` to
`zitadel.idp.v1.ProviderConfig` (v1 APIs).
- Add `IDP_TYPE_ZITADEL`, `ZitadelConfig`, `InstanceRolesInfo` in v2
`idp.proto`
- Extend internal/query IDP template querying to include a
`ZitadelIDPTemplate` (incl. issuer, client credentials, scopes, instance
roles info).
- Add/extend integration tests for updating + fetching providers by ID
and listing providers.

# Additional Changes
N/A

# Additional Context
Closes https://github.com/zitadel/zitadel/issues/12051

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-07-10 09:17:49 +02:00
39ad66bded fix: correct scope validation in token exchange (#12312)
## Which Problems Are Solved

The v4.15.3 token exchange hardening (`#12319`, `#12322`) introduced two
regressions:

1. **Logic bug**: scope validation used intersection (`!inSubject ||
!inActor`) instead of union, so any explicit `scope` on a `user_id`
subject always failed — even `openid` when present on the actor token.
2. **Design gap**: even with union logic, scope-less subjects
(`user_id`, `id_token`) cannot satisfy a rule that requires all
requested scopes to exist on input tokens. This breaks documented
impersonation flows (e.g. service account actor + `user_id` subject
requesting `email`).

## How the Problems Are Solved

- **Standard exchange** (no actor, or subject carries scopes): keep
union validation — requested scopes must be ⊆ subject ∪ actor. For plain
exchange this is effectively a subset of the subject token.
- **Scope-less subject impersonation** (`user_id`, `id_token` on actor
path): split validation:
- **Subject-data scopes** (`openid`, `profile`, `email`, …): client
allowlist only
- **Authorization scopes** (`offline_access`, `:aud`, `projects:roles`,
`role:*`): still ⊆ subject ∪ actor
- Restore subject → actor fallback when `scope` is omitted.

GHSA protections remain: cross-client token binding and
authorization-scope escalation are still rejected.

Closes #12319
Closes #12322

## Additional Changes

- Unit tests for scope validators (`token_exchange_test.go`)
- Integration tests covering `user_id`/`id_token` paths, union-path
rejection, and client-credentials actor → `user_id` exchange

## Additional Context

- Relates to https://github.com/zitadel/zitadel/releases/tag/v4.15.3
- Security fix: GHSA-vrh8-c9cm-wh8v

---------

Co-authored-by: Cursor <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-07-09 12:33:11 +00:00
9d60e83d6f Merge commit from fork
* Use slices.Contains over custom function

* Correctly remove roles from granted roles

* fix(setup): repair user grants with stale roles (GHSA-v859-c572-qh5p)

Add setup step 73 that reconciles existing user grants whose roles were
left too broad by the buggy cascade removal in removeRoleFromUserGrant.
The corruption lives in the eventstore event payloads, so the step pushes
a corrective user.grant.cascade.changed event per affected grant (roles
intersected with the currently valid set) and re-triggers the user grant
projection. Runs in the second setup slice, after the projection tables
it reads have been created.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* fix(setup): scope GHSA-v859-c572-qh5p repair to grant-based user grants

Direct user grants can never be hit by this bug (only ChangeProjectGrant's
multi-role cascade to grant-based grants can trigger it), so drop the
direct-grant branch from the finder query to avoid stripping unrelated,
legitimate roles that merely mismatch for other reasons (e.g. stale
role_key drift). Also exclude removed instances from the migration scope,
and log the number of grants fixed per instance.

Co-authored-by: Cursor <[email protected]>

---------

Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: Livio Spring <[email protected]>
Co-authored-by: Cursor <[email protected]>
2026-07-09 13:28:09 +02:00
942607e0e9 feat: implement UpdateZitadelProvider in ManagementService (#12384)
# Which Problems Are Solved

This PR adds support for updating ZITADEL identity provider (IDP)
templates.

# How the Problems Are Solved

- Implements `UpdateZitadelProvider` in the Management gRPC server plus
converter
- Introduces an org-scoped `ZitadelIDPChanged` event and registers its
event mapper.
- Adds command-side support to update org Zitadel providers and appends
the new event to the org write model.
- Extends the IDP template projection reducer to accept org change
events.

# Additional Changes
N/A

# Additional Context
Closes https://github.com/zitadel/zitadel/issues/11922
Follow up for PRs:

- https://github.com/zitadel/zitadel/pull/12018
- https://github.com/zitadel/zitadel/pull/12020
- https://github.com/zitadel/zitadel/pull/12055
- https://github.com/zitadel/zitadel/pull/12056
- https://github.com/zitadel/zitadel/pull/12371
- https://github.com/zitadel/zitadel/pull/12378

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: Livio Spring <[email protected]>
2026-07-07 04:32:18 +00:00
653a968d91 feat: implement instance-level UpdateZitadelProvider (#12378)
# Which Problems Are Solved

This PR implements the instance-level `UpdateZitadelProvider` endpoint,
enabling updates to existing instance Zitadel IdP templates.

# How the Problems Are Solved

- Added `AdminService.UpdateZitadelProvider` handler, converter
- Added the command-layer implementation to update a ZitadelProvider and
push `instance.idp.zitadel.changed` event
- Added projection-layer implementation to persist Zitadel provider
updates into `projections.idp_templates6_zitadel`
- Added unit and integration tests


# Additional Changes
N/A

# Additional Context
Related to https://github.com/zitadel/zitadel/issues/11922
Follow-up for PRs:
- https://github.com/zitadel/zitadel/pull/12018
- https://github.com/zitadel/zitadel/pull/12020
- https://github.com/zitadel/zitadel/pull/12055
- https://github.com/zitadel/zitadel/pull/12056
- https://github.com/zitadel/zitadel/pull/12371

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-07-06 10:18:35 +02:00
Livio SpringandGitHub 1e0b810dca feat: allow managing invite code in secret generators (#12109)
# Which Problems Are Solved

Zitadel exposes the secrets generator configuration through its admin
api. This allows instance admins to manage them on their own and they
can create overwrite the system / runtime defaults (incl. expiration).
This very much needed in multi-instance scenarios such as zitadel.cloud.
Currently the invite code configuration was not manageable through the
API, but only runtime config.

# How the Problems Are Solved

- added the `invite_code` type to the API allowing it to be set and
retrieved.
- added the type to console's management list
- added the type to be stored on instance setup
- change the `GetSecretGenerator` endpoint to fall back to the runtime
config if no config is stored on the instance itself
- ensure the `length` and at least one charset is enabled, return an
error otherwise
- expiry is not enforced, so 0 allows codes with no expiry (current
state)

# Additional Changes

None

# Additional Context

- closes https://github.com/zitadel/zitadel/issues/10474
2026-07-01 04:53:16 +00:00
f9995ee39c fix: increase performance of ListUser by login name ignore case (#12350)
# Which Problems Are Solved

Login v2 uses the `users.v2.ListUsers`-endpoint to get a user by login
name. This query had an inefficient `WHERE`-clause.

# How the Problems Are Solved

Update the view and use a specific clause for this query.

# Additional information

Added in https://github.com/zitadel/zitadel/pull/10475

---------

Co-authored-by: Marco A. <[email protected]>
Co-authored-by: Livio Spring <[email protected]>
2026-06-30 11:20:21 +00:00
Wim Van LaerandGitHub 2399513643 Merge commit from fork
* fix: added client and scope validation for token exchange

Verify that the token exchange is not cross client

Only yield scopes which were already on the initial token

* comments

* added test
2026-06-22 11:38:49 +02:00
Livio SpringandGitHub 76fd6d859d Merge commit from fork
* fix: ensure external user's email is verified before auto-linking

* fix linking
2026-06-22 11:38:21 +02:00
Livio SpringandGitHub dbb0da71af fix: remove unnecessary entry from default denylist (#12294)
# Which Problems Are Solved

The updated default denylist added an entry for IPv4-mapped IPv6
addresses to prevent IPv6 encapsulation bypasses.
This is not necessary since the IP already gets resolved into v4 and now
blocks them all.

# How the Problems Are Solved

Removed the entry.

# Additional Changes

None

# Additional Context

None
2026-06-16 16:52:26 +02:00
Gayathri VijayanandGitHub 0973b074b4 Merge commit from fork
* fix: client_id verification during code exchange and refresh token flows

* add clientID check for device token flow

* Trigger Build
2026-06-16 15:19:56 +02:00
Tim MöhlmannandGitHub e94d4c3986 feat(crypto): FIPS 140-3 compliant build and runtime checks (#12233)
# Which Problems Are Solved

Enable FIPS 140-3 compliant build.

# How the Problems Are Solved

- Add runtime config validation, if the FIPS flag is enabled fail the
application when a non-compliant hasher is used, or throw a warning when
a legacy verifier is used
- Add a build matrix for FIPS certified build:
  - Go binary is built with `GOFIPS140=certified`
- Login container uses a separate base:
[ubi9](https://catalog.redhat.com/en/software/containers/ubi9/ubi/615bcf606feffc5384e8452e)
from redhat which provides a FIPS certified OpenSSL (used by NodeJS TLS
stack)
- Non-FIPS images where already pushed to both Github Container Registry
and Google Artifact Repository (GAR). Fips images are only pushed to the
GAR.
- Tag versions are suffixed `-fips`. So on release the following images
will be additionally available:

```
europe-docker.pkg.dev/zitadel-common/zitadel-repo/zitadel-login:vX.Y.Z-fips
europe-docker.pkg.dev/zitadel-common/zitadel-repo/zitadel:vX.Y.Z-fips-debug
europe-docker.pkg.dev/zitadel-common/zitadel-repo/zitadel:vX.Y.Z-fips
```
  
# Other changes

- Bumb Go toolchain. At least v1.25.10 is required for a
GOFIPS140=certified setting.
 
# Additional Context

- Closes https://github.com/zitadel/zitadel/issues/4335
- Build [test
run](https://github.com/zitadel/zitadel/actions/runs/27253916052)
pushing FIPS and non-FIPS images
2026-06-16 10:16:49 +02:00
8e82ec1cb9 Merge commit from fork
* Add DenyLists parsing

* Remove unneeded returned error

* Plug global denylist into Command

* app creation: apply denylist to backchannel logout URI

* Inject denylist to backchannel logout worker

* webhook config: validate against blocked URLs

* Add notificationsWebhook denylist target

* command: Add SMTP endpoint validation against blocklist

* command: Add SMS endpoint validation against blocklist

* Validate webhook endpoint against denylist on channel notification

* Remove unused tests

* handle deprecated denylists

* remove unintended denylist entry in deprecated list

* use single http client

* fix tests

* update comments

* fixes

* cleanup

* address comments

* fix merge

---------

Co-authored-by: Livio Spring <[email protected]>
2026-06-15 15:36:14 +02:00
Livio SpringandGitHub d184e976fc Merge commit from fork
* feat(jwt idp): manage and validate audience

* translations

* fix tests

* address comments

* update migration version

* fix merge
2026-06-15 15:27:47 +02:00
Livio SpringandGitHub fad02c6d9f Merge commit from fork 2026-06-15 14:29:08 +02:00
6082e59d47 fix(eventstore): allow overwriting resource owner of events (#12261)
# Which Problems Are Solved

- The eventstore did not support intentionally overwriting the resource
owner when creating events for aggregates that may be reused across
owners.
- Resource owner handling was implicit and could not be controlled per
command/event type.
- We needed a safe way to distinguish between:
  - keeping the existing aggregate owner, and
  - explicitly setting a new owner for specific create-like events.

# How the Problems Are Solved

- Introduced a new eventstore command type with an explicit
enforce_owner flag.
- Updated eventstore.commands_to_events and eventstore.push so owner
assignment is now explicit:
  - if enforce_owner is true, the command owner is written
- if enforce_owner is false, the existing aggregate owner is retained
when present
- Added EnforceResourceOwnerCommand and wiring so command types can opt
in to enforced owner behavior.
- Wired the new behavior through the v3 eventstore push path, including
compatibility fallback for older command type mapping.
- Added migration/setup changes to register and use the new command type
and SQL functions.
- Added and updated tests for owner overwrite and aggregate ID reuse
scenarios.

# Additional Changes

- Added small migration/setup robustness improvements related to
eventstore setup ordering and helper reuse.
- Added focused test coverage for enforced owner behavior and
sequencing.
- Events that currently allow owner changes (implement
EnforceResourceOwner) are:
  - AddedEvent (action)
  - GroupAddedEvent
  - StartedEvent (idp intent)
  - ProjectAddedEvent
  - HumanAddedEvent
  - HumanRegisteredEvent
  - MachineAddedEvent
  - CreatedEvent (schema user)

# Additional Context

- Follow-up for eventstore owner-handling correctness in create flows
and aggregate ID reuse cases.
- No additional issue link was attached for this change.

---------

Co-authored-by: abhishek kumar gupta <[email protected]>
2026-06-15 11:24:37 +02:00
EvanandGitHub cf4554b82c fix(idp): apply PKCE when building OAuth and OIDC providers (#12247)
# Which Problems Are Solved

- IDP intent authorization redirects used by Login v2 ignored the
configured `UsePKCE` setting for Generic OAuth providers
- This caused providers such as X/Twitter OAuth2 to receive
authorization requests without `code_challenge` and
`code_challenge_method`
- OIDC provider construction had the same gap, even though PKCE is
already part of the provider configuration model
- Existing IDP intent redirect tests expected non-PKCE OAuth URLs and
failed once PKCE was applied correctly

# How the Problems Are Solved

- Updated `OAuthIDPWriteModel.ToProvider` in
internal/command/idp_model.go to pass `rp.WithPKCE(nil)` when `UsePKCE`
is enabled
- Updated `OIDCIDPWriteModel.ToProvider` to apply the same PKCE
relying-party option for OIDC providers

# Additional Changes

- Added focused provider-construction tests covering:
    - OAuth provider redirects include code_challenge
    - OIDC provider redirects include code_challenge
    - both providers use code_challenge_method=S256
    - both persist the generated codeVerifier for token exchange
- Updated `TestCommands_AuthFromProvider` in
internal/command/idp_intent_test.go so OAuth redirect assertions verify
PKCE structurally instead of hard-coding the generated challenge value

# Additional Context

- Reproduced with X/Twitter OAuth2 where the generated authorization URL
was missing PKCE parameters despite `usePkce: true`
- Verified both the focused PKCE tests and the full unit test suite run
successfully with the fix
- Closes #12036 
- Closes/supersedes #12054:
  - Tests are included
  - No slice re-allocation on `opts` append
  
# Result

### Before

`authUrl` in `StartIdentityProviderIntent` response is missing
`code_challenge` and `code_challenge_method` for Generic OAuth IDP with
PKCE enabled:
```json
{
    "details": {
        "sequence": "1",
        "changeDate": "2026-06-07T18:48:16.921317Z",
        "resourceOwner": "376298239768395779"
    },
    "authUrl": "https://x.com/i/oauth2/authorize?client_id=<REDACTED>&prompt=select_account&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fidps%2Fcallback&response_type=code&scope=tweet.read+users.email+users.read+offline.access&state=376417136207200259"
}
```

### After

`code_challenge` and `code_challenge_method` are correctly included into
`authUrl`:

```json
{
    "details": {
        "sequence": "1",
        "changeDate": "2026-06-07T18:49:39.488941Z",
        "resourceOwner": "376298239768395779"
    },
    "authUrl": "https://x.com/i/oauth2/authorize?client_id=<REDACTED>&code_challenge=8G4vN8QNgSsbvGSHKwYPEc2qUYU2BK5L0fsr992duTA&code_challenge_method=S256&prompt=select_account&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fidps%2Fcallback&response_type=code&scope=tweet.read+users.email+users.read+offline.access&state=376417274736672771"
}
```
2026-06-11 19:52:11 +02:00
Marco A.andGitHub ed09b3df7f Merge commit from fork 2026-06-08 16:41:08 +02:00
25e263394e chore: update passwap v0.12.1 and align hash validation defaults/errors (#12179)
# Which Problems Are Solved

- Upgrading to `zitadel/passwap` v0.12.1 introduced new encoded-hash
validation paths that still had review feedback open.
- Secret hasher defaults were internally inconsistent (`Hasher.Cost: 4`
vs `Limits.Bcrypt.MinCost: 10`), which could reject hashes created by
the configured hasher.
- New validation error IDs/messages and test coverage needed to be
aligned with project conventions and expected behavior branches.

# How the Problems Are Solved

- Kept the dependency upgrade to `zitadel/passwap` v0.12.1 and completed
the validation integration.
- Updated `ValidateEncodedHash` error handling in
`internal/crypto/passwap.go` to:
  - use unique random-style error IDs,
  - return `Errors.Hash.NotSupported` for no-verifier cases,
  - keep invalid-hash branches mapped to invalid argument errors.
- Expanded `TestHasher_ValidateEncodedHash` in
`internal/crypto/passwap_test.go` to cover and assert:
  - bounds error branch,
  - no-verifier branch,
  - generic invalid-hash branch,
  - expected ZITADEL error IDs/messages.
- Restored lost inline verifier-context comments for argon2 and md5plain
verifier entries.

# Additional Changes

- Added the missing explanatory `Limits` comment for `SecretHasher` in
`cmd/defaults.yaml`.
- Corrected `SecretHasher.Limits.Bcrypt.MinCost` from `10` to `4` to
match the configured default bcrypt cost and avoid configuration
footguns.

# Additional Context

- Follow-up for PR review feedback in
https://github.com/zitadel/zitadel/pull/12179#pullrequestreview-4313121965

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: Livio Spring <[email protected]>
2026-06-05 14:48:35 +02:00
f85a2373c5 chore(test): streamline integration tests for instance management (#12243)
- Removed redundant relational instance handling in integration tests
for adding and removing custom domains.
- Simplified test cases by consolidating instance creation and context
management.
- Enhanced clarity and maintainability of test logic by reducing
complexity in test structures.

# Which Problems Are Solved

`backed/v3` tests are flaky, but the code is not productive. Development
is paused for the moment. Disabling flaky tests helps us to maintain the
product easier.

# How the Problems Are Solved

- Removed redundant relational instance handling in integration tests
for adding and removing custom domains.
- Simplified test cases by consolidating instance creation and context
management.
- Enhanced clarity and maintainability of test logic by reducing
complexity in test structures.newly introduced terms).

# Additional Context

- related to https://github.com/zitadel/zitadel/pull/12241

---------

Co-authored-by: Livio Spring <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-06-05 11:36:45 +00:00
Livio SpringandGitHub 08007da70e Merge commit from fork 2026-05-04 07:05:54 +02:00
Livio SpringandGitHub cc74a36b65 chore(deps): update go dependencies (#12094)
This PR updates all (possible) go dependencies and requires a backport
to v4.x
2026-04-23 14:04:10 +02:00
Marco A.andGitHub 14acc60edd feat: ListSessions to relational (#11987)
# Which Problems Are Solved

This PR introduces the possibility of using the relational DB when
calling the ListSession gRPC endpoint.

# How the Problems Are Solved

  - Implement the Querier interface for ListSession:
- Create a `domain` model for the Session object to be able to map the
gRPC session into it.
- Match the permission filters on ES side to be sure the same sessions
are returned
- Implement converter methods to go from `gRPC` to `domain` models (both
ways)
- Fix the session sql relational migration: rework the trigger to update
the `expiration` field to perform the update only when the input
`lifetime` has a non-zero value.
  - Link the Querier implementation with the gRPC endpoint
- Run the same integration tests against the relational DB, making sure
the outcome is the same. ⚠️ Due to missing permission checks, some
divergence is expected. Hence, specific code to circumvent the
differences has been put in place

# Additional Context

- Closes #11039
2026-04-16 10:58:17 +02:00
Tim MöhlmannandGitHub 177589a0a8 fix(grpc): increase MaxSendMsgSize (#12066)
# Which Problems Are Solved

Users exporting larger orgsanizations were facing grpc message size
limits of 4 MiB, while trying to export 6.3 MiB of data. Other export
methods like S3 aren't implemented.

# How the Problems Are Solved

Set MaxSendMsgSize to 10 MiB (allow some overhead). This is not a
long-term solution and we should investigate better ways of export.

# Additional Changes

- none

# Additional Context

- Support ticket
2026-04-15 13:04:22 +00:00
Gayathri VijayanandGitHub e19bb7a173 feat: implement AddZitadelProvider in ManagementService (#12056)
# Which Problems Are Solved

This PR adds implementation to add a Zitadel IdP at the
organization-level.

# How the Problems Are Solved
- Added handling/converters for the `AddZitadelProvider` endpoint in
`ManagementService` in the server layer
- Registered a new `org.idp.zitadel.added` event for org-level Zitadel
providers
- Added `AddOrgZitadelProvider` command to validate the request and push
`org.idp.zitadel.added` event to the eventstore
- Added the `org.idp.zitadel.added` event to the projection reducer
- Added unit and integration tests

# Additional Changes
added more tests for the ZitadelProvider in AdminService

# Additional Context
- Closes https://github.com/zitadel/zitadel/issues/11823
- Follow-up for PRs https://github.com/zitadel/zitadel/pull/12018,
https://github.com/zitadel/zitadel/pull/12020,
https://github.com/zitadel/zitadel/pull/12055
2026-04-15 14:22:45 +02:00
Gayathri VijayanandGitHub 55a9acf3bf feat: projection layer implementation to add Zitadel provider (#12055)
# Which Problems Are Solved

Persisting instance-level Zitadel provider in the projections.

# How the Problems Are Solved
- Defining a new projection table `projections.idp_templates6_zitadel`
and columns for the Zitadel provider
- Adding a reducer `reduceZitadelIDPAdded` to process instance-level
`ZitadelIDPAddedEvent`
- Unit tests 


# Additional Changes
N/A


# Additional Context
- Related to https://github.com/zitadel/zitadel/issues/11823
- Follow-up for PRs https://github.com/zitadel/zitadel/pull/12018,
https://github.com/zitadel/zitadel/pull/12020
2026-04-15 07:59:52 +02:00
7b9d2b7d17 feat: add administrator role permission table (#11817)
This update introduces a new table for managing administrator role
permissions, along with the necessary repository and projection logic to
handle adding and removing permissions. It also includes tests to ensure
the correct functionality of the permission management system.

closes https://github.com/zitadel/zitadel/issues/10219

---------

Co-authored-by: Marco Ardizzone <[email protected]>
2026-04-14 06:01:52 +00:00
bb3b52dda3 feat: command layer implementation for AddZitadelProvider (#12020)
# Which Problems Are Solved

This PR contains the command-layer implementation to add an instance IDP
of the type `ZitadelProvider`

# How the Problems Are Solved
- Implementing `AddZitadelProvider` in AdminService 
- Adding the command-layer to create a `ZitadelProvider` and push
`ZitadelIDPAddedEvent`

# Additional Changes
N/A

# Additional Context
- Related to https://github.com/zitadel/zitadel/issues/11823
- Follow-up for PR https://github.com/zitadel/zitadel/pull/12018

---------

Co-authored-by: Copilot <[email protected]>
2026-04-13 15:05:36 +00:00
01fe34a526 fix(oidc): use authenticated encryption for opaque tokens (#12017)
# Which Problems Are Solved

Opaque tokens now use authenticated encryption.

# How the Problems Are Solved

- Upgrade zitadel/oidc to v3.47
- Copy crypto implementation for refresh and session tokens (internal to
zitadel)
- Added config that allows validating old tokens for gradual roll-out

# Additional Changes

- Set NX cache for `integration-test-build` to `false`, working on a
seperate fix.

# Additional Context

- closes #11315

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: muhlemmer <[email protected]>
2026-04-13 10:59:50 +00:00
a2bf528ca0 feat(domain): introduce error slugs (#12030)
# Which Problems Are Solved

As part of https://github.com/zitadel/zitadel/issues/11917 we want to
introduce error slugs so (API) clients can rely on stable,
machine-readable errors and act accordingly.

# How the Problems Are Solved

- Added a `NewSlug` helper function in the domain package.
- Added `ErrorDetails` to the `ZitadelError`
- Added an `zitadel.error.v2.ErrorDetail` proto message
- Updated the connectRPC error interceptor to map new slug based errors
to the new `ErrorDetail`
- Defined some common slugs and error functions like internal errors
- Defined (session) specific slugs used in the `DeleteSession` and
`CheckUser` functions and replaced old implementations
- Updated integration tests to check specific errors if the relation
database feature is enabled
- Updated doc and guideline to reflect the latest changes and decisions
- Updated DeleteSession endpoint API to list possible slugs

# Additional Changes

None

# Additional Context

- closes #11957

---------

Co-authored-by: Wim Van Laer <[email protected]>
2026-04-13 09:47:04 +02:00
fbd43ced6e fix(grpc): return 401 for unauthenticated v1 gateway errors (#11786)
Fixes #11730

The v1 gRPC middleware can return native gRPC status errors such as
`codes.Unauthenticated` when the auth header is missing.

Those errors were being passed through the generic gRPC error converter,
which only handled ZITADEL errors and downgraded raw gRPC statuses to
`codes.Unknown`.

Through grpc-gateway that caused `/auth/v1/users/me` to return HTTP 500
instead of HTTP 401.

So this change preserves native gRPC status errors in
`ZITADELToGRPCError`, keeps `ExtractZITADELError` aligned with those
transport codes for activity reporting, and adds regression coverage for
the converter, middleware, and gateway HTTP behavior.

---------

Co-authored-by: Gayathri Vijayan <[email protected]>
2026-04-10 12:22:40 +00:00
Vitor Bari BucciantiandGitHub 035ac4b9a2 fix(api): Add dummy implementation of new LinksSettings APIs to satisfy SettingsServiceHandler interface (#12034)
# Which Problems Are Solved

#11975 introduces new APIs to `SettingsService`, however,
`settingsconnect.SettingsServiceHandler` wasn't updated to satisfy the
interface containing the new APIs.

# How the Problems Are Solved

By adding a dummy implementation of new RPC methods to the
SettingsService Server.

# Additional Changes

n/a 

# Additional Context

n/a
2026-04-10 13:57:32 +02:00
Mridang AgarwallaandGitHub ce31ee2272 fix: propagate non-NotFound errors from instance interceptor (#12019) 2026-04-10 08:22:56 +00:00
b558a1f79f feat: allow ECDSA and ED25519 public keys (#11819)
# Which Problems Are Solved
Currently ZITADEL only allows the use of RSA public keys for machine
user authentication (jwt-bearer grant), including for system API users.
Attempting to use ECDSA (e.g. P-256) or ED25519 keys results in
`Errors.Internal` because `BytesToPublicKey` performs an
`ifc.(*rsa.PublicKey)` type assertion that returns `(nil, nil)` for
non-RSA keys, which then causes a nil key panic in go-jose during JWT
verification.

This is the same fix as #8433 (by @livio-a), rebased onto current
`main`.

# How the Problems Are Solved
- `BytesToPublicKey` now returns `crypto.PublicKey` (the standard
library interface) instead of `*rsa.PublicKey`
- A type switch validates the parsed key is one of `*rsa.PublicKey`,
`*ecdsa.PublicKey`, or `ed25519.PublicKey`
- A new `ErrNoPublicKey` sentinel error is returned for unsupported key
types instead of silently returning nil
- Callers in `system_token.go` and `query/key.go` are updated to use the
generic `crypto.PublicKey` interface

# Additional Changes
None

# Additional Context
Duplicate of #8433 which has been open since August 2024. We hit this
bug while implementing OIDC bootstrap for an SGX enclave that generates
ECDSA P-256 keys at runtime -- the `AddKey` API accepts the ECDSA SPKI
PEM fine, but the subsequent `jwt-bearer` token exchange fails with
`Errors.Internal` due to the nil key.

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Wim Van Laer <[email protected]>
2026-04-09 11:30:23 +02:00
Livio SpringandGitHub fbb6a406c8 chore: fix generators in crypto package (#12008)
# Which Problems Are Solved

`@zitadel/api:generate-go` failed due to duplicate generated files.
https://github.com/zitadel/zitadel/pull/11820 removed the old generated
file and added a generate command to the `internal/crypto/crypto.go`
file. However, there was already a `internal/crypto/generate.go` with a
different output file name (the old file).

# How the Problems Are Solved

Removed the `internal/crypto/generate.go` file and moved the second
generate into `internal/crypto/code.go`.

# Additional Changes

Noticed that mockgen is an old version and updated it. Also then checked
all other tools and updated them.

# Additional Context

- relates to #11820
- noted internally
2026-04-08 08:48:05 +02:00
Wim Van LaerandGitHub 99ad1ea83d test: added checks for timestamps in passkey test (#12003)
# Which Problems Are Solved

A test was failing because of timezone flakiness

# How the Problems Are Solved

The actual problem was an `updatedAt` field was not filled in because of
the `createdAt` was missing on an event. This caused a zero value to be
filled in into the `updatedAt` field. Postgres then stored this value
with seconds in it's timezone info, which go could not store.

By adding filling in the `createdAt` field, this does not occur.
2026-04-07 16:27:45 +02:00
c7f92a6887 feat: session challenge passkey for the RT model (#11944)
# Which Problems Are Solved

Add Passkey challenge needed for Create/Set session in the RT model.

# How the Problems Are Solved

Introduce `PasskeyChallengeCommand` (validate/execute/events) for
session creation checks
Add a generic `BeginWebAuthNLogin` helper that returns session data +
assertion JSON bytes.
Add unit tests

# Additional Changes
N/A

# Additional Context
- Related to https://github.com/zitadel/zitadel/issues/11035

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Marco A. <[email protected]>
2026-04-01 12:13:40 +02:00
5344a7f584 fix: invalid jwt assertion error handling (#11933)
# Which Problems Are Solved

Incorrectly mapped errors on the `/oauth/v2/token` endpoint lead to a
large number of HTTP status 500 errors.

# How the Problems Are Solved

By mapping invalid jwt assertion errors to OIDC `invalid_client` errors,
which returns a HTTP status 400.

# Additional Changes

N/A

# Additional Context

- Closes https://github.com/zitadel/zitadel/issues/11924
- Follow-up: 
- Fix the [error
handling](https://github.com/zitadel/oidc/blob/main/pkg/oidc/verifier.go#L195)
in the oidc package

---------

Co-authored-by: Copilot <[email protected]>
2026-04-01 10:44:02 +02:00
Marco A.andGitHub 7a15a06d69 fix: reducer for PasskeyVerified sets VerifiedAt (#11929)
# Which Problems Are Solved

In https://github.com/zitadel/zitadel/pull/11858#discussion_r2993742914
we discussed on how to translate the ES passkey state to a relational
one. That is used to filter out passkeys during convertion to webauthn
credentials.

It was decided to consider passkeys in ready state those that have a
verified at `time.Time` set.

The change required fixing the reducer for the eventstore event.

# How the Problems Are Solved

  - Set `VerifiedAt` once `HumanWebAuthNVerifiedEvent` is received
  - Also set the verification to `nil`

# Additional Context

- Discussion #11858
- Follow-up for PR #11858
2026-03-31 17:38:47 +02:00
8e41d288ff fix: use preparation filter for org existence check during setup (#11932)
<!--
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

- Creating an organization via `SetUpOrg` failed when a custom domain
was provided in the same request.
- The org-domain setup path checked org existence only against persisted
state, so it could not see the newly created organization before the
batch was pushed.

# How the Problems Are Solved

- Added a preparation-aware org existence check that resolves the org
through the validation filter instead of the direct persisted-state
lookup.
- Reused the transaction-aware preparation filter so later validations
can see earlier in-flight commands from the same `PrepareCommands`
batch.

fixes #11677

---------

Co-authored-by: abhishek kumar gupta <[email protected]>
Co-authored-by: Wim Van Laer <[email protected]>
2026-03-31 09:58:42 +02:00
21b28b56ac fix: revert feature key for configs back to ConsoleUseV2UserApi (#11928)
# Which Problems Are Solved

https://github.com/zitadel/zitadel/pull/11390 renamed "Console" to
"Management Console". While
https://github.com/zitadel/zitadel/pull/11706 already reverted an
unintended rename of the feature key to enable the management console to
use the V2 API for user creation. It was now also discovered that the
rename of the feature itself also broke existing (default)
configurations.

# How the Problems Are Solved

Added a `mapstructure` tag on the instance feature to handle existing
configs.

# Additional Changes

Removed unused `TokenExchange` from the default configuration.

# Additional Context

- relates to #11390 
- relates to #11706
- requires backport to v4.x

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Marco A. <[email protected]>
2026-03-30 15:59:57 +00:00
Livio SpringandGitHub 0390e324e4 fix: do not send init mails for admins on instance setup (#11744)
# Which Problems Are Solved

Currently when setting up an instance, for example from the customer
portal through system api, an instance is created together with an
administrator. If no admin user is specified the default user from the
runtime configuration is automatically added.
For the new onboarding, we can to create instances without prompting the
user to set up a complete account right on start, but the current
behavior of the API prevents this, resp. the created account would
fallback to the default user or password.
By providing an empty `password` field in the `owner_password` in the
`AddInstanceRequest` or `huiman.password` in the
`CreateInstanceRequest`, it's already possible to create an account
without password. Until now this however ended up in an initial mail to
be sent to the user to finalize their account setup.

# How the Problems Are Solved

We simply set the `allowInitMail` to false in the `AddHumanCommand` for
setting up the admins. This will prevent an email to be sent out
immediately and gives us the possibility to use the invite flow later
on.

# Additional Changes

None

# Additional Context

- required for https://github.com/zitadel/website/issues/1611
- backport to v4.x
2026-03-30 15:31:51 +00:00
022bf74060 feat(session): Passkey Check API with relation tables (#11858)
# Which Problems Are Solved

As part of #11035 , this PR implements the Passkey check logic for
session validation

# How the Problems Are Solved

  - Refactor webauth FinishLogin to support new domain model
  - Add webauth config to defaults
  - Implement passkey check logic and tests
- Manual transaction management to avoid stalling the DB while
FinishLogin callback is executed
- Update passkey Type condition to allow passing a text operation
(equal, contains, etc..)

# Additional Context

This is a cherry-picked PR + minor changes, coming from
https://github.com/zitadel/zitadel/pull/11164
- Relates to #11035

---------

Co-authored-by: Fabienne Bühler <[email protected]>
Co-authored-by: Gayathri Vijayan <[email protected]>
2026-03-27 12:38:40 +01:00
ec7a6d5526 fix: make recovery code active on add (#11734)
# 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]>
2026-03-27 09:47:16 +00:00
Livio SpringandGitHub f94e4065c2 chore: update go dependencies (#11883)
Updates all dependencies to latests versions (apart from the ones where
there are already issues to solve their updates).
Some updates required minor changes.
2026-03-24 12:27:43 +01:00
70adaff793 feat: add option to use x.509 certificate system-api-user tokens (#11876)
# Which Problems Are Solved

System API users currently authenticate using raw RSA public keys
configured via Path or KeyData. This approach doesn't integrate well
with Kubernetes tooling.

# How the Problems Are Solved

Allow for the `path`/`keyData` to be an X.509 certificate. 

The `NotBefore` and `NotAfter` fields of the certificate are beeing
respected when validating the JWT.

# Additional Changes

# Additional Context

- Closes #11442

---------

Co-authored-by: Livio Spring <[email protected]>
2026-03-23 13:32:27 +00:00
c6386cb807 feat: rt recovery code check (#11848)
# Which Problems Are Solved

Adding recovery code check step required for the CreateSession RT
implementation.

# How the Problems Are Solved

- Introduce `RecoveryCodeCheckCommand` (validate/execute/events) for
session creation checks
- Add unit tests

# Additional Changes
- refactor password-check code to reuse a shared lockout-policy helper
- add some missing error translations in `internal/static/i18n/en.yaml`

# Additional Context
- Related to https://github.com/zitadel/zitadel/issues/11035

---------

Co-authored-by: Silvan <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-03-23 10:56:40 +01:00