feat: handle Zitadel provider IdP login via login v1 (#12469)

# Which Problems Are Solved

This PR adds support for using a ZITADEL IdP provider in the login v1 UI
flow and conditionally grants a support-user instance membership based
on a ZITADEL-specific project-roles token claim.

# How the Problems Are Solved

- Introduced ZITADEL IdP handling in the login v1 handler, including
extracting the `urn:zitadel:iam:org:project:roles` claim and granting
`IAM_OWNER_VIEWER` instance membership when configured orgs match.
- Added a new `AddInstanceMemberFromLogin` to assign an instance
membership during the login v1 ZITADEL-IdP flow without permission
checks (as the authorization is established based on the project roles
in the token claim)
- Added unit tests

# Additional Changes

N/A

# Additional Context
- Closes https://github.com/zitadel/zitadel/issues/12446
This commit is contained in:
gayathri
2026-07-28 15:20:46 +02:00
committed by GitHub
parent 318acd4bc3
commit ffd9b39bdb
14 changed files with 908 additions and 492 deletions
+6 -9
View File
@@ -2049,15 +2049,12 @@ func (c *Commands) validateOrgZitadelProvider(provider *ZitadelProvider, create
if create && provider.ClientSecret == "" {
return zerrors.ThrowInvalidArgument(nil, "ORG-DxaSb9", "Errors.Invalid.Argument")
}
for i := range provider.InstanceRolesInfo {
provider.InstanceRolesInfo[i].OrganizationID = strings.TrimSpace(provider.InstanceRolesInfo[i].OrganizationID)
if provider.InstanceRolesInfo[i].OrganizationID == "" {
return zerrors.ThrowInvalidArgument(nil, "ORG-M0QmjB", "Errors.Invalid.Argument")
}
provider.InstanceRolesInfo[i].OrganizationDomain = strings.TrimSpace(provider.InstanceRolesInfo[i].OrganizationDomain)
if provider.InstanceRolesInfo[i].OrganizationDomain == "" {
return zerrors.ThrowInvalidArgument(nil, "ORG-HAELEz", "Errors.Invalid.Argument")
}
// instance_roles_info must never be set on an organization-scoped Zitadel provider:
// it drives instance-wide role grants on login, and honoring it here would let an
// org owner escalate themselves to instance-level roles. Only the instance-scoped
// Admin API may configure it.
if len(provider.InstanceRolesInfo) > 0 {
return zerrors.ThrowInvalidArgument(nil, "ORG-ImOVF3", "Errors.Invalid.Argument")
}
return nil
}