From 61b40975f774e6b97e2c975af1f06c9234d34aa0 Mon Sep 17 00:00:00 2001 From: Gayathri Vijayan <66356931+grvijayan@users.noreply.github.com> Date: Fri, 10 Apr 2026 09:40:05 +0200 Subject: [PATCH] feat: API definition to add new Zitadel providers (#12018) # Which Problems Are Solved In the Zitadel API, provide an IdP template which allows connecting to other Zitadel instances. # How the Problems Are Solved This PR adds API definitions to add Zitadel provider at instance and organization levels. - Add `AddZitadelProvider` to ManagementService and AdminService - Add `InstanceRolesInfo` message to help determine instance admin role assignments # Additional Changes N/A # Additional Context - Related to https://github.com/zitadel/zitadel/issues/11823 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- proto/zitadel/admin.proto | 69 ++++++++++++++++++++++++++++++ proto/zitadel/idp.proto | 17 ++++++++ proto/zitadel/management.proto | 78 ++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) diff --git a/proto/zitadel/admin.proto b/proto/zitadel/admin.proto index 621b46253..2d5a250ca 100644 --- a/proto/zitadel/admin.proto +++ b/proto/zitadel/admin.proto @@ -2253,6 +2253,24 @@ service AdminService { }; } + // Add a new Zitadel identity provider in the instance + rpc AddZitadelProvider(AddZitadelProviderRequest) returns (AddZitadelProviderResponse) { + option (google.api.http) = { + post: "/idps/zitadel" + body: "*" + }; + + option (zitadel.v1.auth_option) = { + permission: "iam.idp.write" + }; + + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: "Identity Providers"; + summary: "Add Zitadel Identity Provider"; + description: "Add a new Zitadel identity provider"; + }; + } + // Remove an identity provider // Will remove all linked providers of this configuration on the users rpc DeleteProvider(DeleteProviderRequest) returns (DeleteProviderResponse) { @@ -7283,6 +7301,57 @@ message RegenerateSAMLProviderCertificateResponse { zitadel.v1.ObjectDetails details = 1; } +message AddZitadelProviderRequest { + string name = 1 [ + (validate.rules).string = {min_len: 1, max_len: 200}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "\"Zitadel\""; + } + ]; + string issuer = 2 [ + (validate.rules).string = {min_len: 1, max_len: 200}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "\"https://zitadel.example.com/\""; + description: "the OIDC issuer of the identity provider"; + } + ]; + string client_id = 3 [ + (validate.rules).string = {min_len: 1, max_len: 200}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "\"client-id\""; + description: "client id generated by the identity provider"; + } + ]; + string client_secret = 4 [ + (validate.rules).string = {min_len: 1, max_len: 1000}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "\"secret\""; + description: "secret generated by the identity provider"; + } + ]; + repeated string scopes = 5 [ + (validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "[\"openid\", \"profile\", \"email\"]"; + description: "the scopes requested by Zitadel during the request on the identity provider"; + } + ]; + zitadel.idp.v1.Options provider_options = 6; + + bool is_id_token_mapping = 7; + // Enable the use of Proof Key for Code Exchange (PKCE) for the OIDC flow. + bool use_pkce = 8; + + // Optionally specify the details (organization_id, organization_domain) related to instance roles. + // It is used to determine if a user should be assigned instance administrator roles after authenticating with the provider. + repeated zitadel.idp.v1.InstanceRolesInfo instance_roles_info = 9 [(validate.rules).repeated = {max_items: 20}]; +} + +message AddZitadelProviderResponse { + zitadel.v1.ObjectDetails details = 1; + string id = 2; +} + message DeleteProviderRequest { string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}]; } diff --git a/proto/zitadel/idp.proto b/proto/zitadel/idp.proto index 222374953..488bde0a6 100644 --- a/proto/zitadel/idp.proto +++ b/proto/zitadel/idp.proto @@ -611,3 +611,20 @@ message AppleConfig { } ]; } + +message InstanceRolesInfo { + string organization_id = 1 [ + (validate.rules).string = {min_len: 1, max_len: 200}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "\"69629023906488334\""; + description: "the id of the organization"; + } + ]; + string organization_domain = 2 [ + (validate.rules).string = {min_len: 1, max_len: 200}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "\"example-org.com\""; + description: "the domain of the organization"; + } + ]; +} diff --git a/proto/zitadel/management.proto b/proto/zitadel/management.proto index 156f4c6b5..ed5d1c7f2 100644 --- a/proto/zitadel/management.proto +++ b/proto/zitadel/management.proto @@ -8163,6 +8163,32 @@ service ManagementService { }; } + // Add a new Zitadel identity provider in the organization + rpc AddZitadelProvider(AddZitadelProviderRequest) returns (AddZitadelProviderResponse) { + option (google.api.http) = { + post: "/idps/zitadel" + body: "*" + }; + + option (zitadel.v1.auth_option) = { + permission: "org.idp.write" + }; + + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: "Identity Providers"; + summary: "Add Zitadel Identity Provider"; + description: ""; + parameters: { + headers: { + name: "x-zitadel-orgid"; + description: "The default is always the organization of the requesting user. If you like to get/set a result of another organization include the header. Make sure the user has permission to access the requested data."; + type: STRING, + required: false; + }; + }; + }; + } + // Remove an identity provider // Will remove all linked providers of this configuration on the users rpc DeleteProvider(DeleteProviderRequest) returns (DeleteProviderResponse) { @@ -14024,6 +14050,58 @@ message UpdateAppleProviderResponse { zitadel.v1.ObjectDetails details = 1; } +message AddZitadelProviderRequest { + string name = 1 [ + (validate.rules).string = {min_len: 1, max_len: 200}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "\"Zitadel\""; + } + ]; + string issuer = 2 [ + (validate.rules).string = {min_len: 1, max_len: 200}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "\"https://zitadel.example.com/\""; + description: "the OIDC issuer of the identity provider"; + } + ]; + string client_id = 3 [ + (validate.rules).string = {min_len: 1, max_len: 200}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "\"client-id\""; + description: "client id generated by the identity provider"; + } + ]; + string client_secret = 4 [ + (validate.rules).string = {min_len: 1, max_len: 1000}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "\"secret\""; + description: "secret generated by the identity provider"; + } + ]; + repeated string scopes = 5 [ + (validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + example: "[\"openid\", \"profile\", \"email\"]"; + description: "the scopes requested by Zitadel during the request on the identity provider"; + } + ]; + zitadel.idp.v1.Options provider_options = 6; + + bool is_id_token_mapping = 7; + // Enable the use of Proof Key for Code Exchange (PKCE) for the OIDC flow. + bool use_pkce = 8; + + // Optionally specify the details (organization_id, organization_domain) related to instance roles. + // It is used to determine if a user should be assigned instance administrator roles after authenticating with the provider. + repeated zitadel.idp.v1.InstanceRolesInfo instance_roles_info = 9 [(validate.rules).repeated = {max_items: 20}]; +} + +message AddZitadelProviderResponse { + zitadel.v1.ObjectDetails details = 1; + string id = 2; +} + + message DeleteProviderRequest { string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}]; }