Files
zitadel/backend/v3/domain/id_provider.go
T
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

342 lines
13 KiB
Go

package domain
import (
"context"
"encoding/json"
"time"
"github.com/zitadel/zitadel/backend/v3/storage/database"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
)
//go:generate enumer -type IDPType -transform lower -trimprefix IDPType
type IDPType uint8
const (
IDPTypeOIDC IDPType = iota + 1
IDPTypeJWT
IDPTypeOAuth
IDPTypeSAML
IDPTypeLDAP
IDPTypeGitHub
IDPTypeGitHubEnterprise
IDPTypeGitLab
IDPTypeGitLabSelfHosted
IDPTypeAzure
IDPTypeGoogle
IDPTypeApple
)
//go:generate enumer -type IDPState -transform lower -trimprefix IDPState -sql
type IDPState uint8
const (
IDPStateActive IDPState = iota
IDPStateInactive
)
//go:generate enumer -type IDPAutoLinkingField -transform lower -trimprefix IDPAutoLinkingField
type IDPAutoLinkingField uint8
const (
IDPAutoLinkingFieldUsername IDPAutoLinkingField = iota + 1
IDPAutoLinkingFieldEmail
)
type OIDCMappingField int8
const (
OIDCMappingFieldUnspecified OIDCMappingField = iota
OIDCMappingFieldPreferredLoginName
OIDCMappingFieldEmail
// count is for validation purposes
//nolint: unused
oidcMappingFieldCount
)
type IdentityProvider struct {
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
OrgID *string `json:"orgId,omitempty" db:"org_id"`
ID string `json:"id,omitempty" db:"id"`
State IDPState `json:"state,omitempty" db:"state"`
Name string `json:"name,omitempty" db:"name"`
// Type represents the type of and idp. It is a pointer because it can be nil during the migration of the events
Type *IDPType `json:"type,omitempty" db:"type"`
AllowCreation bool `json:"allowCreation,omitempty" db:"allow_creation"`
AllowAutoCreation bool `json:"allowAutoCreation,omitempty" db:"allow_auto_creation"`
AllowAutoUpdate bool `json:"allowAutoUpdate,omitempty" db:"allow_auto_update"`
AllowLinking bool `json:"allowLinking,omitempty" db:"allow_linking"`
AutoLinkingField *IDPAutoLinkingField `json:"autoLinkingField,omitempty" db:"auto_linking_field"`
Payload json.RawMessage `json:"payload,omitempty" db:"payload"`
CreatedAt time.Time `json:"createdAt,omitzero" db:"created_at"`
UpdatedAt time.Time `json:"updatedAt,omitzero" db:"updated_at"`
}
type OIDC struct {
ClientID string `json:"clientId,omitempty"`
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
Issuer string `json:"issuer,omitempty"`
AuthorizationEndpoint string `json:"authorizationEndpoint,omitempty"`
TokenEndpoint string `json:"tokenEndpoint,omitempty"`
Scopes []string `json:"scopes,omitempty"`
IDPDisplayNameMapping OIDCMappingField `json:"IDPDisplayNameMapping,omitempty"`
UserNameMapping OIDCMappingField `json:"usernameMapping,omitempty"`
IsIDTokenMapping bool `json:"idTokenMapping,omitempty"`
UsePKCE bool `json:"usePKCE,omitempty"`
}
type IDPOIDC struct {
*IdentityProvider
OIDC
}
type JWT struct {
IDPConfigID string `json:"idpConfigId"`
JWTEndpoint string `json:"jwtEndpoint,omitempty"`
Issuer string `json:"issuer,omitempty"`
KeysEndpoint string `json:"keysEndpoint,omitempty"`
HeaderName string `json:"headerName,omitempty"`
Audience string `json:"audience,omitempty"`
}
type IDPJWT struct {
*IdentityProvider
JWT
}
type OAuth struct {
ClientID string `json:"clientId,omitempty"`
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
AuthorizationEndpoint string `json:"authorizationEndpoint,omitempty"`
TokenEndpoint string `json:"tokenEndpoint,omitempty"`
UserEndpoint string `json:"userEndpoint,omitempty"`
Scopes []string `json:"scopes,omitempty"`
IDAttribute string `json:"idAttribute,omitempty"`
UsePKCE bool `json:"usePKCE,omitempty"`
}
type IDPOAuth struct {
*IdentityProvider
OAuth
}
//go:generate enumer -type AzureTenantType -transform lower -trimprefix AzureTenantType
type AzureTenantType uint8
const (
AzureTenantTypeCommon AzureTenantType = iota
AzureTenantTypeOrganizations
AzureTenantTypeConsumers
)
type Azure struct {
ClientID string `json:"client_id,omitempty"`
ClientSecret *crypto.CryptoValue `json:"client_secret,omitempty"`
Scopes []string `json:"scopes,omitempty"`
Tenant AzureTenantType `json:"tenant,omitempty"`
IsEmailVerified bool `json:"isEmailVerified,omitempty"`
}
type IDPAzureAD struct {
*IdentityProvider
Azure
}
type Google struct {
ClientID string `json:"clientId"`
ClientSecret *crypto.CryptoValue `json:"clientSecret"`
Scopes []string `json:"scopes,omitempty"`
}
type IDPGoogle struct {
*IdentityProvider
Google
}
type Github struct {
ClientID string `json:"clientId"`
ClientSecret *crypto.CryptoValue `json:"clientSecret"`
Scopes []string `json:"scopes,omitempty"`
}
type IDPGithub struct {
*IdentityProvider
Github
}
type GithubEnterprise struct {
ClientID string `json:"clientId,omitempty"`
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
AuthorizationEndpoint string `json:"authorizationEndpoint,omitempty"`
TokenEndpoint string `json:"tokenEndpoint,omitempty"`
UserEndpoint string `json:"userEndpoint,omitempty"`
Scopes []string `json:"scopes,omitempty"`
}
type IDPGithubEnterprise struct {
*IdentityProvider
GithubEnterprise
}
type Gitlab struct {
ClientID string `json:"clientId,omitempty"`
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
Scopes []string `json:"scopes,omitempty"`
}
type IDPGitlab struct {
*IdentityProvider
Gitlab
}
type GitlabSelfHosted struct {
Issuer string `json:"issuer"`
ClientID string `json:"clientId,omitempty"`
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
Scopes []string `json:"scopes,omitempty"`
}
type IDPGitlabSelfHosted struct {
*IdentityProvider
GitlabSelfHosted
}
type LDAP struct {
Servers []string `json:"servers"`
StartTLS bool `json:"startTLS"`
BaseDN string `json:"baseDN"`
BindDN string `json:"bindDN"`
BindPassword *crypto.CryptoValue `json:"bindPassword"`
UserBase string `json:"userBase"`
UserObjectClasses []string `json:"userObjectClasses"`
UserFilters []string `json:"userFilters"`
Timeout time.Duration `json:"timeout"`
RootCA []byte `json:"rootCA"`
LDAPAttributes
}
type LDAPAttributes struct {
IDAttribute string `json:"idAttribute,omitempty"`
FirstNameAttribute string `json:"firstNameAttribute,omitempty"`
LastNameAttribute string `json:"lastNameAttribute,omitempty"`
DisplayNameAttribute string `json:"displayNameAttribute,omitempty"`
NickNameAttribute string `json:"nickNameAttribute,omitempty"`
PreferredUsernameAttribute string `json:"preferredUsernameAttribute,omitempty"`
EmailAttribute string `json:"emailAttribute,omitempty"`
EmailVerifiedAttribute string `json:"emailVerifiedAttribute,omitempty"`
PhoneAttribute string `json:"phoneAttribute,omitempty"`
PhoneVerifiedAttribute string `json:"phoneVerifiedAttribute,omitempty"`
PreferredLanguageAttribute string `json:"preferredLanguageAttribute,omitempty"`
AvatarURLAttribute string `json:"avatarURLAttribute,omitempty"`
ProfileAttribute string `json:"profileAttribute,omitempty"`
}
type IDPLDAP struct {
*IdentityProvider
LDAP
}
type Apple struct {
ClientID string `json:"clientId"`
TeamID string `json:"teamId"`
KeyID string `json:"keyId"`
PrivateKey *crypto.CryptoValue `json:"privateKey"`
Scopes []string `json:"scopes,omitempty"`
}
type IDPApple struct {
*IdentityProvider
Apple
}
type SAML struct {
Metadata []byte `json:"metadata,omitempty"`
Key *crypto.CryptoValue `json:"key,omitempty"`
Certificate []byte `json:"certificate,omitempty"`
Binding string `json:"binding,omitempty"`
WithSignedRequest bool `json:"withSignedRequest,omitempty"`
NameIDFormat *domain.SAMLNameIDFormat `json:"nameIDFormat,omitempty"`
TransientMappingAttributeName string `json:"transientMappingAttributeName,omitempty"`
FederatedLogoutEnabled bool `json:"federatedLogoutEnabled,omitempty"`
SignatureAlgorithm string `json:"signatureAlgorithm,omitempty"`
}
type IDPSAML struct {
*IdentityProvider
SAML
}
type idProviderColumns interface {
InstanceIDColumn() database.Column
OrgIDColumn() database.Column
IDColumn() database.Column
StateColumn() database.Column
NameColumn() database.Column
TypeColumn() database.Column
AllowCreationColumn() database.Column
AllowAutoCreationColumn() database.Column
AllowAutoUpdateColumn() database.Column
AllowLinkingColumn() database.Column
AutoLinkingFieldColumn() database.Column
PayloadColumn() database.Column
CreatedAtColumn() database.Column
UpdatedAtColumn() database.Column
}
type idProviderConditions interface {
// PrimaryKeyCondition returns a filter on the primary key fields.
PrimaryKeyCondition(instanceID, idpID string) database.Condition
InstanceIDCondition(id string) database.Condition
OrgIDCondition(id *string) database.Condition
IDCondition(id string) database.Condition
StateCondition(state IDPState) database.Condition
NameCondition(op database.TextOperation, name string) database.Condition
TypeCondition(typee IDPType) database.Condition
}
type idProviderChanges interface {
SetName(name string) database.Change
SetState(state IDPState) database.Change
SetAllowCreation(allow bool) database.Change
SetAllowAutoCreation(allow bool) database.Change
SetAllowAutoUpdate(allow bool) database.Change
SetAllowLinking(allow bool) database.Change
SetAutoLinkingField(field *IDPAutoLinkingField) database.Change
SetPayload(payload string) database.Change
SetUpdatedAt(updatedAt *time.Time) database.Change
// SetType is used for migrating generic idps to specific types.
SetType(typee IDPType) database.Change
}
type IDProviderRepository interface {
Repository
idProviderColumns
idProviderConditions
idProviderChanges
Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IdentityProvider, error)
List(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) ([]*IdentityProvider, error)
Create(ctx context.Context, client database.QueryExecutor, idp *IdentityProvider) error
Update(ctx context.Context, client database.QueryExecutor, condition database.Condition, changes ...database.Change) (int64, error)
Delete(ctx context.Context, client database.QueryExecutor, condition database.Condition) (int64, error)
GetOIDC(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPOIDC, error)
GetJWT(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPJWT, error)
GetOAuth(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPOAuth, error)
GetAzureAD(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPAzureAD, error)
GetGoogle(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPGoogle, error)
GetGithub(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPGithub, error)
GetGithubEnterprise(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPGithubEnterprise, error)
GetGitlab(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPGitlab, error)
GetGitlabSelfHosted(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPGitlabSelfHosted, error)
GetLDAP(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPLDAP, error)
GetApple(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPApple, error)
GetSAML(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*IDPSAML, error)
}