2021-01-28 05:35:26 +00:00
|
|
|
package command
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-07-06 11:55:57 +00:00
|
|
|
"reflect"
|
|
|
|
"time"
|
|
|
|
|
2022-04-26 23:01:45 +00:00
|
|
|
"github.com/zitadel/zitadel/internal/crypto"
|
|
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
|
|
"github.com/zitadel/zitadel/internal/eventstore"
|
|
|
|
"github.com/zitadel/zitadel/internal/repository/project"
|
2021-01-28 05:35:26 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type OIDCApplicationWriteModel struct {
|
|
|
|
eventstore.WriteModel
|
|
|
|
|
|
|
|
AppID string
|
|
|
|
AppName string
|
|
|
|
ClientID string
|
2024-04-05 09:35:49 +00:00
|
|
|
HashedSecret string
|
2021-01-28 05:35:26 +00:00
|
|
|
ClientSecretString string
|
|
|
|
RedirectUris []string
|
|
|
|
ResponseTypes []domain.OIDCResponseType
|
|
|
|
GrantTypes []domain.OIDCGrantType
|
|
|
|
ApplicationType domain.OIDCApplicationType
|
|
|
|
AuthMethodType domain.OIDCAuthMethodType
|
|
|
|
PostLogoutRedirectUris []string
|
|
|
|
OIDCVersion domain.OIDCVersion
|
|
|
|
Compliance *domain.Compliance
|
|
|
|
DevMode bool
|
|
|
|
AccessTokenType domain.OIDCTokenType
|
|
|
|
AccessTokenRoleAssertion bool
|
|
|
|
IDTokenRoleAssertion bool
|
|
|
|
IDTokenUserinfoAssertion bool
|
|
|
|
ClockSkew time.Duration
|
|
|
|
State domain.AppState
|
2021-05-19 07:17:38 +00:00
|
|
|
AdditionalOrigins []string
|
2023-04-11 15:07:32 +00:00
|
|
|
SkipNativeAppSuccessPage bool
|
2021-06-27 09:20:59 +00:00
|
|
|
oidc bool
|
2021-01-28 05:35:26 +00:00
|
|
|
}
|
|
|
|
|
2021-02-22 11:27:47 +00:00
|
|
|
func NewOIDCApplicationWriteModelWithAppID(projectID, appID, resourceOwner string) *OIDCApplicationWriteModel {
|
2021-01-28 05:35:26 +00:00
|
|
|
return &OIDCApplicationWriteModel{
|
|
|
|
WriteModel: eventstore.WriteModel{
|
|
|
|
AggregateID: projectID,
|
|
|
|
ResourceOwner: resourceOwner,
|
|
|
|
},
|
|
|
|
AppID: appID,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewOIDCApplicationWriteModel(projectID, resourceOwner string) *OIDCApplicationWriteModel {
|
|
|
|
return &OIDCApplicationWriteModel{
|
|
|
|
WriteModel: eventstore.WriteModel{
|
|
|
|
AggregateID: projectID,
|
|
|
|
ResourceOwner: resourceOwner,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2022-01-03 08:19:07 +00:00
|
|
|
func (wm *OIDCApplicationWriteModel) AppendEvents(events ...eventstore.Event) {
|
2021-01-28 05:35:26 +00:00
|
|
|
for _, event := range events {
|
|
|
|
switch e := event.(type) {
|
|
|
|
case *project.ApplicationAddedEvent:
|
|
|
|
if e.AppID != wm.AppID {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wm.WriteModel.AppendEvents(e)
|
|
|
|
case *project.ApplicationChangedEvent:
|
|
|
|
if e.AppID != wm.AppID {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wm.WriteModel.AppendEvents(e)
|
|
|
|
case *project.ApplicationDeactivatedEvent:
|
|
|
|
if e.AppID != wm.AppID {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wm.WriteModel.AppendEvents(e)
|
|
|
|
case *project.ApplicationReactivatedEvent:
|
|
|
|
if e.AppID != wm.AppID {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wm.WriteModel.AppendEvents(e)
|
|
|
|
case *project.ApplicationRemovedEvent:
|
|
|
|
if e.AppID != wm.AppID {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wm.WriteModel.AppendEvents(e)
|
|
|
|
case *project.OIDCConfigAddedEvent:
|
|
|
|
if e.AppID != wm.AppID {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wm.WriteModel.AppendEvents(e)
|
|
|
|
case *project.OIDCConfigChangedEvent:
|
|
|
|
if e.AppID != wm.AppID {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wm.WriteModel.AppendEvents(e)
|
|
|
|
case *project.OIDCConfigSecretChangedEvent:
|
|
|
|
if e.AppID != wm.AppID {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wm.WriteModel.AppendEvents(e)
|
2024-04-05 09:35:49 +00:00
|
|
|
case *project.OIDCConfigSecretHashUpdatedEvent:
|
|
|
|
if e.AppID != wm.AppID {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wm.WriteModel.AppendEvents(e)
|
2021-01-28 05:35:26 +00:00
|
|
|
case *project.ProjectRemovedEvent:
|
|
|
|
wm.WriteModel.AppendEvents(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (wm *OIDCApplicationWriteModel) Reduce() error {
|
|
|
|
for _, event := range wm.Events {
|
|
|
|
switch e := event.(type) {
|
|
|
|
case *project.ApplicationAddedEvent:
|
|
|
|
wm.AppName = e.Name
|
|
|
|
wm.State = domain.AppStateActive
|
|
|
|
case *project.ApplicationChangedEvent:
|
|
|
|
wm.AppName = e.Name
|
|
|
|
case *project.ApplicationDeactivatedEvent:
|
|
|
|
if wm.State == domain.AppStateRemoved {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wm.State = domain.AppStateInactive
|
|
|
|
case *project.ApplicationReactivatedEvent:
|
|
|
|
if wm.State == domain.AppStateRemoved {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
wm.State = domain.AppStateActive
|
|
|
|
case *project.ApplicationRemovedEvent:
|
|
|
|
wm.State = domain.AppStateRemoved
|
|
|
|
case *project.OIDCConfigAddedEvent:
|
|
|
|
wm.appendAddOIDCEvent(e)
|
|
|
|
case *project.OIDCConfigChangedEvent:
|
|
|
|
wm.appendChangeOIDCEvent(e)
|
|
|
|
case *project.OIDCConfigSecretChangedEvent:
|
2024-04-05 09:35:49 +00:00
|
|
|
wm.HashedSecret = crypto.SecretOrEncodedHash(e.ClientSecret, e.HashedSecret)
|
|
|
|
case *project.OIDCConfigSecretHashUpdatedEvent:
|
|
|
|
wm.HashedSecret = e.HashedSecret
|
2021-01-28 05:35:26 +00:00
|
|
|
case *project.ProjectRemovedEvent:
|
|
|
|
wm.State = domain.AppStateRemoved
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return wm.WriteModel.Reduce()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (wm *OIDCApplicationWriteModel) appendAddOIDCEvent(e *project.OIDCConfigAddedEvent) {
|
2021-06-27 09:20:59 +00:00
|
|
|
wm.oidc = true
|
2021-01-28 05:35:26 +00:00
|
|
|
wm.ClientID = e.ClientID
|
2024-04-05 09:35:49 +00:00
|
|
|
wm.HashedSecret = crypto.SecretOrEncodedHash(e.ClientSecret, e.HashedSecret)
|
2021-01-28 05:35:26 +00:00
|
|
|
wm.RedirectUris = e.RedirectUris
|
|
|
|
wm.ResponseTypes = e.ResponseTypes
|
|
|
|
wm.GrantTypes = e.GrantTypes
|
|
|
|
wm.ApplicationType = e.ApplicationType
|
|
|
|
wm.AuthMethodType = e.AuthMethodType
|
|
|
|
wm.PostLogoutRedirectUris = e.PostLogoutRedirectUris
|
|
|
|
wm.OIDCVersion = e.Version
|
|
|
|
wm.DevMode = e.DevMode
|
|
|
|
wm.AccessTokenType = e.AccessTokenType
|
|
|
|
wm.AccessTokenRoleAssertion = e.AccessTokenRoleAssertion
|
|
|
|
wm.IDTokenRoleAssertion = e.IDTokenRoleAssertion
|
|
|
|
wm.IDTokenUserinfoAssertion = e.IDTokenUserinfoAssertion
|
|
|
|
wm.ClockSkew = e.ClockSkew
|
2021-05-19 07:17:38 +00:00
|
|
|
wm.AdditionalOrigins = e.AdditionalOrigins
|
2023-04-11 15:07:32 +00:00
|
|
|
wm.SkipNativeAppSuccessPage = e.SkipNativeAppSuccessPage
|
2021-01-28 05:35:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (wm *OIDCApplicationWriteModel) appendChangeOIDCEvent(e *project.OIDCConfigChangedEvent) {
|
|
|
|
if e.RedirectUris != nil {
|
|
|
|
wm.RedirectUris = *e.RedirectUris
|
|
|
|
}
|
|
|
|
if e.ResponseTypes != nil {
|
|
|
|
wm.ResponseTypes = *e.ResponseTypes
|
|
|
|
}
|
|
|
|
if e.GrantTypes != nil {
|
|
|
|
wm.GrantTypes = *e.GrantTypes
|
|
|
|
}
|
|
|
|
if e.ApplicationType != nil {
|
|
|
|
wm.ApplicationType = *e.ApplicationType
|
|
|
|
}
|
|
|
|
if e.AuthMethodType != nil {
|
|
|
|
wm.AuthMethodType = *e.AuthMethodType
|
|
|
|
}
|
|
|
|
if e.PostLogoutRedirectUris != nil {
|
|
|
|
wm.PostLogoutRedirectUris = *e.PostLogoutRedirectUris
|
|
|
|
}
|
|
|
|
if e.Version != nil {
|
|
|
|
wm.OIDCVersion = *e.Version
|
|
|
|
}
|
|
|
|
if e.DevMode != nil {
|
|
|
|
wm.DevMode = *e.DevMode
|
|
|
|
}
|
|
|
|
if e.AccessTokenType != nil {
|
|
|
|
wm.AccessTokenType = *e.AccessTokenType
|
|
|
|
}
|
|
|
|
if e.AccessTokenRoleAssertion != nil {
|
|
|
|
wm.AccessTokenRoleAssertion = *e.AccessTokenRoleAssertion
|
|
|
|
}
|
|
|
|
if e.IDTokenRoleAssertion != nil {
|
|
|
|
wm.IDTokenRoleAssertion = *e.IDTokenRoleAssertion
|
|
|
|
}
|
|
|
|
if e.IDTokenUserinfoAssertion != nil {
|
|
|
|
wm.IDTokenUserinfoAssertion = *e.IDTokenUserinfoAssertion
|
|
|
|
}
|
|
|
|
if e.ClockSkew != nil {
|
|
|
|
wm.ClockSkew = *e.ClockSkew
|
|
|
|
}
|
2021-05-19 07:17:38 +00:00
|
|
|
if e.AdditionalOrigins != nil {
|
|
|
|
wm.AdditionalOrigins = *e.AdditionalOrigins
|
|
|
|
}
|
2023-04-11 15:07:32 +00:00
|
|
|
if e.SkipNativeAppSuccessPage != nil {
|
|
|
|
wm.SkipNativeAppSuccessPage = *e.SkipNativeAppSuccessPage
|
|
|
|
}
|
2021-01-28 05:35:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (wm *OIDCApplicationWriteModel) Query() *eventstore.SearchQueryBuilder {
|
2021-07-06 11:55:57 +00:00
|
|
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
2021-02-18 13:48:27 +00:00
|
|
|
ResourceOwner(wm.ResourceOwner).
|
2021-07-06 11:55:57 +00:00
|
|
|
AddQuery().
|
|
|
|
AggregateTypes(project.AggregateType).
|
|
|
|
AggregateIDs(wm.AggregateID).
|
2021-02-18 13:48:27 +00:00
|
|
|
EventTypes(
|
|
|
|
project.ApplicationAddedType,
|
|
|
|
project.ApplicationChangedType,
|
|
|
|
project.ApplicationDeactivatedType,
|
|
|
|
project.ApplicationReactivatedType,
|
|
|
|
project.ApplicationRemovedType,
|
|
|
|
project.OIDCConfigAddedType,
|
|
|
|
project.OIDCConfigChangedType,
|
|
|
|
project.OIDCConfigSecretChangedType,
|
2024-04-05 09:35:49 +00:00
|
|
|
project.OIDCConfigSecretHashUpdatedType,
|
|
|
|
project.ProjectRemovedType,
|
|
|
|
).Builder()
|
2021-01-28 05:35:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (wm *OIDCApplicationWriteModel) NewChangedEvent(
|
|
|
|
ctx context.Context,
|
2021-02-18 13:48:27 +00:00
|
|
|
aggregate *eventstore.Aggregate,
|
2021-02-22 11:27:47 +00:00
|
|
|
appID string,
|
2021-01-28 05:35:26 +00:00
|
|
|
redirectURIS,
|
|
|
|
postLogoutRedirectURIs []string,
|
|
|
|
responseTypes []domain.OIDCResponseType,
|
|
|
|
grantTypes []domain.OIDCGrantType,
|
|
|
|
appType domain.OIDCApplicationType,
|
|
|
|
authMethodType domain.OIDCAuthMethodType,
|
|
|
|
oidcVersion domain.OIDCVersion,
|
|
|
|
accessTokenType domain.OIDCTokenType,
|
|
|
|
devMode,
|
|
|
|
accessTokenRoleAssertion,
|
|
|
|
idTokenRoleAssertion,
|
|
|
|
idTokenUserinfoAssertion bool,
|
|
|
|
clockSkew time.Duration,
|
2021-05-19 07:17:38 +00:00
|
|
|
additionalOrigins []string,
|
2023-04-11 15:07:32 +00:00
|
|
|
skipNativeAppSuccessPage bool,
|
2021-01-28 05:35:26 +00:00
|
|
|
) (*project.OIDCConfigChangedEvent, bool, error) {
|
|
|
|
changes := make([]project.OIDCConfigChanges, 0)
|
|
|
|
var err error
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(wm.RedirectUris, redirectURIS) {
|
|
|
|
changes = append(changes, project.ChangeRedirectURIs(redirectURIS))
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(wm.ResponseTypes, responseTypes) {
|
|
|
|
changes = append(changes, project.ChangeResponseTypes(responseTypes))
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(wm.GrantTypes, grantTypes) {
|
|
|
|
changes = append(changes, project.ChangeGrantTypes(grantTypes))
|
|
|
|
}
|
|
|
|
if wm.ApplicationType != appType {
|
|
|
|
changes = append(changes, project.ChangeApplicationType(appType))
|
|
|
|
}
|
|
|
|
if wm.AuthMethodType != authMethodType {
|
|
|
|
changes = append(changes, project.ChangeAuthMethodType(authMethodType))
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(wm.PostLogoutRedirectUris, postLogoutRedirectURIs) {
|
|
|
|
changes = append(changes, project.ChangePostLogoutRedirectURIs(postLogoutRedirectURIs))
|
|
|
|
}
|
|
|
|
if wm.OIDCVersion != oidcVersion {
|
|
|
|
changes = append(changes, project.ChangeVersion(oidcVersion))
|
|
|
|
}
|
|
|
|
if wm.DevMode != devMode {
|
|
|
|
changes = append(changes, project.ChangeDevMode(devMode))
|
|
|
|
}
|
|
|
|
if wm.AccessTokenType != accessTokenType {
|
|
|
|
changes = append(changes, project.ChangeAccessTokenType(accessTokenType))
|
|
|
|
}
|
|
|
|
if wm.AccessTokenRoleAssertion != accessTokenRoleAssertion {
|
|
|
|
changes = append(changes, project.ChangeAccessTokenRoleAssertion(accessTokenRoleAssertion))
|
|
|
|
}
|
|
|
|
if wm.IDTokenRoleAssertion != idTokenRoleAssertion {
|
|
|
|
changes = append(changes, project.ChangeIDTokenRoleAssertion(idTokenRoleAssertion))
|
|
|
|
}
|
|
|
|
if wm.IDTokenUserinfoAssertion != idTokenUserinfoAssertion {
|
|
|
|
changes = append(changes, project.ChangeIDTokenUserinfoAssertion(idTokenUserinfoAssertion))
|
|
|
|
}
|
|
|
|
if wm.ClockSkew != clockSkew {
|
|
|
|
changes = append(changes, project.ChangeClockSkew(clockSkew))
|
|
|
|
}
|
2021-05-19 07:17:38 +00:00
|
|
|
if !reflect.DeepEqual(wm.AdditionalOrigins, additionalOrigins) {
|
|
|
|
changes = append(changes, project.ChangeAdditionalOrigins(additionalOrigins))
|
|
|
|
}
|
2023-04-11 15:07:32 +00:00
|
|
|
if wm.SkipNativeAppSuccessPage != skipNativeAppSuccessPage {
|
|
|
|
changes = append(changes, project.ChangeSkipNativeAppSuccessPage(skipNativeAppSuccessPage))
|
|
|
|
}
|
|
|
|
|
2021-01-28 05:35:26 +00:00
|
|
|
if len(changes) == 0 {
|
|
|
|
return nil, false, nil
|
|
|
|
}
|
2021-02-18 13:48:27 +00:00
|
|
|
changeEvent, err := project.NewOIDCConfigChangedEvent(ctx, aggregate, appID, changes)
|
2021-01-28 05:35:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, false, err
|
|
|
|
}
|
|
|
|
return changeEvent, true, nil
|
|
|
|
}
|
2021-06-27 09:20:59 +00:00
|
|
|
|
|
|
|
func (wm *OIDCApplicationWriteModel) IsOIDC() bool {
|
|
|
|
return wm.oidc
|
|
|
|
}
|