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
This commit is contained in:
Gayathri Vijayan
2026-04-15 14:22:45 +02:00
committed by GitHub
parent 55a9acf3bf
commit e19bb7a173
16 changed files with 1090 additions and 21 deletions
+3 -4
View File
@@ -1,8 +1,6 @@
package admin
import (
"strings"
"github.com/crewjam/saml"
"github.com/muhlemmer/gu"
dsig "github.com/russellhaering/goxmldsig"
@@ -553,10 +551,11 @@ func addZitadelProviderToCommand(req *admin_pb.AddZitadelProviderRequest) comman
instanceRolesInfo := make([]idp.RolesInfo, 0, len(req.InstanceRolesInfo))
for _, info := range req.InstanceRolesInfo {
instanceRolesInfo = append(instanceRolesInfo, idp.RolesInfo{
OrganizationID: strings.TrimSpace(info.OrganizationId),
OrganizationDomain: strings.TrimSpace(info.OrganizationDomain),
OrganizationID: info.OrganizationId,
OrganizationDomain: info.OrganizationDomain,
})
}
return command.ZitadelProvider{
Name: req.Name,
Issuer: req.Issuer,
@@ -207,6 +207,35 @@ func Test_addZitadelProviderToCommand(t *testing.T) {
req *admin_pb.AddZitadelProviderRequest
want command.ZitadelProvider
}{
{
name: "without instance roles info",
req: &admin_pb.AddZitadelProviderRequest{
Name: "Zitadel Support IdP",
ClientId: "test-client",
ClientSecret: "test-secret",
Scopes: []string{"email", "profile", "urn:zitadel:iam:org:project:roles"},
ProviderOptions: &idp_pb.Options{
IsLinkingAllowed: false,
IsCreationAllowed: true,
IsAutoCreation: false,
IsAutoUpdate: true,
AutoLinking: 0,
},
},
want: command.ZitadelProvider{
Name: "Zitadel Support IdP",
ClientID: "test-client",
ClientSecret: "test-secret",
Scopes: []string{"email", "profile", "urn:zitadel:iam:org:project:roles"},
IDPOptions: idp.Options{
IsCreationAllowed: true,
IsAutoCreation: false,
IsLinkingAllowed: false,
IsAutoUpdate: true,
},
InstanceRolesInfo: []idp.RolesInfo{},
},
},
{
name: "all fields filled",
req: &admin_pb.AddZitadelProviderRequest{
@@ -12,6 +12,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/zitadel/zitadel/internal/integration"
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
idp_pb "github.com/zitadel/zitadel/pkg/grpc/idp"
object_pb "github.com/zitadel/zitadel/pkg/grpc/object"
@@ -28,6 +29,34 @@ func Test_AddZitadelProvider(t *testing.T) {
wantErr error
wantResponse *admin_pb.AddZitadelProviderResponse
}{
{
name: "no permissions, error",
args: args{
ctx: Instance.WithAuthorizationToken(CTX, integration.UserTypeNoPermission),
req: &admin_pb.AddZitadelProviderRequest{
Name: "Zitadel Support IdP",
Issuer: "zitadel.example.com",
ClientId: "test-client",
ClientSecret: "test-secret",
Scopes: []string{"email", "profile"},
},
},
wantErr: status.Error(codes.NotFound, "membership not found (AUTHZ-cdgFk)"),
},
{
name: "insufficient permissions, error",
args: args{
ctx: Instance.WithAuthorizationToken(CTX, integration.UserTypeLogin),
req: &admin_pb.AddZitadelProviderRequest{
Name: "Zitadel Support IdP",
Issuer: "zitadel.example.com",
ClientId: "test-client",
ClientSecret: "test-secret",
Scopes: []string{"email", "profile"},
},
},
wantErr: status.Error(codes.PermissionDenied, "No matching permissions found (AUTH-5mWD2)"),
},
{
name: "missing required field: name",
args: args{