[PR #6130] [management] Add Zitadel Management API v2 support #29065

Open
opened 2026-08-05 08:07:23 -04:00 by saavagebueno · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbirdio/netbird/pull/6130
Author: @remipcomaite
Created: 5/12/2026
Status: 🔄 Open

Base: mainHead: feature/zitadel-api-version-config


📝 Commits (3)

  • 3dc5ef4 [management] Add Zitadel Management API v2 support with explicit version config
  • 825355f [management] Fix Zitadel v2 InviteUserByID to include sendCode variant
  • b312064 [management] Add symmetric lastName assertion to Zitadel v1 CreateUser test

📊 Changes

3 files changed (+304 additions, -68 deletions)

View changed files

📝 management/server/idp/idp.go (+1 -0)
📝 management/server/idp/zitadel.go (+112 -65)
📝 management/server/idp/zitadel_test.go (+191 -3)

📄 Description

Describe your changes

Zitadel introduced a v2 Management API with updated REST endpoints and revised field naming conventions. This PR adds full v2 support to the Zitadel IdP manager while preserving complete backward compatibility with existing v1 deployments.

Changes

Dual-version response structs — JSON structs carry both v1 and v2 field names so the same types deserialize responses from either API version:

  • Profile: firstName/lastName (v1) + givenName/familyName (v2)
  • Email verification: isEmailVerified (v1) → isVerified (v2)
  • User ID: id (v1) → userId (v2)

Optional APIVersion config field — set "APIVersion": "v2" in ExtraConfig to enable the v2 API. Any other value (including empty, which is the default) uses v1. This follows the same pattern as the existing PAT field.

v1/v2 branching across all mutating and search methods:

Method v1 v2
CreateUser POST users/human/_import, field userName POST users/human, field username
GetUserByEmail POST users/_search POST users
GetAccount / GetAllAccounts POST users/_search, body "" POST users, body {}
InviteUserByID POST users/{id}/_resend_initialization POST users/{id}/invite_code (CreateInviteCode)
DeleteUser DELETE users/{id} DELETE users/{id} (unchanged)

Note: InviteUserByID v2 uses CreateInviteCode (/invite_code) rather than the deprecated ResendInviteCode (/invite_code/resend), which requires a pre-existing code.

Minor fix — the delete HTTP helper previously logged "unable to get" instead of "unable to delete".

Configuration example

{
  "IdpManagerConfig": {
    "ManagerType": "zitadel",
    "ClientConfig": {
      "ClientID": "...",
      "ClientSecret": "...",
      "GrantType": "client_credentials",
      "TokenEndpoint": "https://instance.zitadel.cloud/oauth/v2/token"
    },
    "ExtraConfig": {
      "ManagementEndpoint": "https://instance.zitadel.cloud/v2",
      "APIVersion": "v2"
    }
  }
}

Omitting APIVersion (or setting it to any value other than "v2") retains the existing v1 behaviour.

N/A

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (the APIVersion field follows the same pattern as the existing PAT field in ExtraConfig)

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

https://github.com/netbirdio/docs/pull/__

Summary by CodeRabbit

  • New Features
    • Added configurable Zitadel API version support with runtime routing for user creation, lookup, invites, and account listing.
  • Bug Fixes / Behavior
    • Improved management HTTP error reporting to surface Zitadel error details on failures.
  • Tests
    • Expanded tests to cover v1 vs v2 request/response shapes, invite behavior, and account search.

Review Change Stack


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbirdio/netbird/pull/6130 **Author:** [@remipcomaite](https://github.com/remipcomaite) **Created:** 5/12/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feature/zitadel-api-version-config` --- ### 📝 Commits (3) - [`3dc5ef4`](https://github.com/netbirdio/netbird/commit/3dc5ef455ad6e3d49f360296cf07ac66dc81f3c7) [management] Add Zitadel Management API v2 support with explicit version config - [`825355f`](https://github.com/netbirdio/netbird/commit/825355fad383c2eee642d9076cec093ccfdb1724) [management] Fix Zitadel v2 InviteUserByID to include sendCode variant - [`b312064`](https://github.com/netbirdio/netbird/commit/b3120642aae5cbb3ff8a6fe3587e663f0dccfed6) [management] Add symmetric lastName assertion to Zitadel v1 CreateUser test ### 📊 Changes **3 files changed** (+304 additions, -68 deletions) <details> <summary>View changed files</summary> 📝 `management/server/idp/idp.go` (+1 -0) 📝 `management/server/idp/zitadel.go` (+112 -65) 📝 `management/server/idp/zitadel_test.go` (+191 -3) </details> ### 📄 Description ## Describe your changes Zitadel introduced a v2 Management API with updated REST endpoints and revised field naming conventions. This PR adds full v2 support to the Zitadel IdP manager while preserving complete backward compatibility with existing v1 deployments. ### Changes **Dual-version response structs** — JSON structs carry both v1 and v2 field names so the same types deserialize responses from either API version: - Profile: `firstName`/`lastName` (v1) + `givenName`/`familyName` (v2) - Email verification: `isEmailVerified` (v1) → `isVerified` (v2) - User ID: `id` (v1) → `userId` (v2) **Optional `APIVersion` config field** — set `"APIVersion": "v2"` in `ExtraConfig` to enable the v2 API. Any other value (including empty, which is the default) uses v1. This follows the same pattern as the existing `PAT` field. **v1/v2 branching across all mutating and search methods:** | Method | v1 | v2 | |---|---|---| | `CreateUser` | `POST users/human/_import`, field `userName` | `POST users/human`, field `username` | | `GetUserByEmail` | `POST users/_search` | `POST users` | | `GetAccount` / `GetAllAccounts` | `POST users/_search`, body `""` | `POST users`, body `{}` | | `InviteUserByID` | `POST users/{id}/_resend_initialization` | `POST users/{id}/invite_code` (`CreateInviteCode`) | | `DeleteUser` | `DELETE users/{id}` | `DELETE users/{id}` (unchanged) | Note: `InviteUserByID` v2 uses `CreateInviteCode` (`/invite_code`) rather than the deprecated `ResendInviteCode` (`/invite_code/resend`), which requires a pre-existing code. **Minor fix** — the `delete` HTTP helper previously logged `"unable to get"` instead of `"unable to delete"`. ### Configuration example ```json { "IdpManagerConfig": { "ManagerType": "zitadel", "ClientConfig": { "ClientID": "...", "ClientSecret": "...", "GrantType": "client_credentials", "TokenEndpoint": "https://instance.zitadel.cloud/oauth/v2/token" }, "ExtraConfig": { "ManagementEndpoint": "https://instance.zitadel.cloud/v2", "APIVersion": "v2" } } } ``` Omitting `APIVersion` (or setting it to any value other than `"v2"`) retains the existing v1 behaviour. ## Issue ticket number and link N/A ## Stack <!-- branch-stack --> ### Checklist - [x] Is it a bug fix - [ ] Is a typo/documentation fix - [x] Is a feature enhancement - [ ] It is a refactor - [x] Created tests that fail without the change (if possible) > By submitting this pull request, you confirm that you have read and agree to the terms of the [Contributor License Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md). ## Documentation Select exactly one: - [ ] I added/updated documentation for this change - [x] Documentation is **not needed** for this change (the `APIVersion` field follows the same pattern as the existing `PAT` field in `ExtraConfig`) ### Docs PR URL (required if "docs added" is checked) Paste the PR link from https://github.com/netbirdio/docs here: https://github.com/netbirdio/docs/pull/__ <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added configurable Zitadel API version support with runtime routing for user creation, lookup, invites, and account listing. * **Bug Fixes / Behavior** * Improved management HTTP error reporting to surface Zitadel error details on failures. * **Tests** * Expanded tests to cover v1 vs v2 request/response shapes, invite behavior, and account search. [![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/netbirdio/netbird/pull/6130) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
saavagebueno added the pull-request label 2026-08-05 08:07:23 -04:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#29065