feat: add additional origins on applications (#1691)

* feat: add additional origins on applications

* app additional redirects

* chore(deps-dev): bump @angular/cli from 11.2.8 to 11.2.11 in /console (#1706)

* fix: show org with regex (#1688)

* fix: flag mapping (#1699)

* chore(deps-dev): bump @angular/cli from 11.2.8 to 11.2.11 in /console

Bumps [@angular/cli](https://github.com/angular/angular-cli) from 11.2.8 to 11.2.11.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v11.2.8...v11.2.11)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump stylelint from 13.10.0 to 13.13.1 in /console (#1703)

* fix: show org with regex (#1688)

* fix: flag mapping (#1699)

* chore(deps-dev): bump stylelint from 13.10.0 to 13.13.1 in /console

Bumps [stylelint](https://github.com/stylelint/stylelint) from 13.10.0 to 13.13.1.
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint/compare/13.10.0...13.13.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @types/node from 14.14.37 to 15.0.1 in /console (#1702)

* fix: show org with regex (#1688)

* fix: flag mapping (#1699)

* chore(deps-dev): bump @types/node from 14.14.37 to 15.0.1 in /console

Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.14.37 to 15.0.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump ts-protoc-gen from 0.14.0 to 0.15.0 in /console (#1701)

* fix: show org with regex (#1688)

* fix: flag mapping (#1699)

* chore(deps): bump ts-protoc-gen from 0.14.0 to 0.15.0 in /console

Bumps [ts-protoc-gen](https://github.com/improbable-eng/ts-protoc-gen) from 0.14.0 to 0.15.0.
- [Release notes](https://github.com/improbable-eng/ts-protoc-gen/releases)
- [Changelog](https://github.com/improbable-eng/ts-protoc-gen/blob/master/CHANGELOG.md)
- [Commits](https://github.com/improbable-eng/ts-protoc-gen/compare/0.14.0...0.15.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @types/jasmine from 3.6.9 to 3.6.10 in /console (#1682)

Bumps [@types/jasmine](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jasmine) from 3.6.9 to 3.6.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jasmine)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump @types/google-protobuf in /console (#1681)

Bumps [@types/google-protobuf](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/google-protobuf) from 3.7.4 to 3.15.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/google-protobuf)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump grpc from 1.24.5 to 1.24.7 in /console (#1666)

Bumps [grpc](https://github.com/grpc/grpc-node) from 1.24.5 to 1.24.7.
- [Release notes](https://github.com/grpc/grpc-node/releases)
- [Commits](https://github.com/grpc/grpc-node/compare/grpc@1.24.5...grpc@1.24.7)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* lock

* chore(deps-dev): bump @angular/language-service from 11.2.9 to 11.2.12 in /console (#1704)

* fix: show org with regex (#1688)

* fix: flag mapping (#1699)

* chore(deps-dev): bump @angular/language-service in /console

Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 11.2.9 to 11.2.12.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/11.2.12/packages/language-service)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* package lock

* downgrade grpc

* downgrade protobuf types

* revert npm packs 🥸

Co-authored-by: Max Peintner <max@caos.ch>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
This commit is contained in:
Livio Amstutz
2021-05-19 09:17:38 +02:00
committed by GitHub
parent 18ed6633be
commit 2e8fa82261
30 changed files with 380 additions and 17 deletions

View File

@@ -52,6 +52,7 @@ func AddOIDCAppRequestToDomain(req *mgmt_pb.AddOIDCAppRequest) *domain.OIDCApp {
IDTokenRoleAssertion: req.IdTokenRoleAssertion,
IDTokenUserinfoAssertion: req.IdTokenUserinfoAssertion,
ClockSkew: req.ClockSkew.AsDuration(),
AdditionalOrigins: req.AdditionalOrigins,
}
}
@@ -90,6 +91,7 @@ func UpdateOIDCAppConfigRequestToDomain(app *mgmt_pb.UpdateOIDCAppConfigRequest)
IDTokenRoleAssertion: app.IdTokenRoleAssertion,
IDTokenUserinfoAssertion: app.IdTokenUserinfoAssertion,
ClockSkew: app.ClockSkew.AsDuration(),
AdditionalOrigins: app.AdditionalOrigins,
}
}

View File

@@ -55,6 +55,8 @@ func AppOIDCConfigToPb(app *proj_model.ApplicationView) *app_pb.App_OidcConfig {
IdTokenRoleAssertion: app.IDTokenRoleAssertion,
IdTokenUserinfoAssertion: app.IDTokenUserinfoAssertion,
ClockSkew: durationpb.New(app.ClockSkew),
AdditionalOrigins: app.AdditionalOrigins,
AllowedOrigins: app.OriginAllowList,
},
}
}

View File

@@ -21,3 +21,12 @@ func IsOriginAllowed(allowList []string, origin string) bool {
}
return false
}
//IsOrigin checks if provided string is an origin (scheme://hostname[:port]) without path, query or fragment
func IsOrigin(rawOrigin string) bool {
parsedUrl, err := url.Parse(rawOrigin)
if err != nil {
return false
}
return parsedUrl.Scheme != "" && parsedUrl.Host != "" && parsedUrl.Path == "" && len(parsedUrl.Query()) == 0 && parsedUrl.Fragment == ""
}

View File

@@ -81,7 +81,8 @@ func (c *Commands) addOIDCApplication(ctx context.Context, projectAgg *eventstor
oidcApp.AccessTokenRoleAssertion,
oidcApp.IDTokenRoleAssertion,
oidcApp.IDTokenUserinfoAssertion,
oidcApp.ClockSkew))
oidcApp.ClockSkew,
oidcApp.AdditionalOrigins))
return events, stringPw, nil
}
@@ -115,7 +116,8 @@ func (c *Commands) ChangeOIDCApplication(ctx context.Context, oidc *domain.OIDCA
oidc.AccessTokenRoleAssertion,
oidc.IDTokenRoleAssertion,
oidc.IDTokenUserinfoAssertion,
oidc.ClockSkew)
oidc.ClockSkew,
oidc.AdditionalOrigins)
if err != nil {
return nil, err
}

View File

@@ -33,6 +33,7 @@ type OIDCApplicationWriteModel struct {
IDTokenUserinfoAssertion bool
ClockSkew time.Duration
State domain.AppState
AdditionalOrigins []string
}
func NewOIDCApplicationWriteModelWithAppID(projectID, appID, resourceOwner string) *OIDCApplicationWriteModel {
@@ -151,6 +152,7 @@ func (wm *OIDCApplicationWriteModel) appendAddOIDCEvent(e *project.OIDCConfigAdd
wm.IDTokenRoleAssertion = e.IDTokenRoleAssertion
wm.IDTokenUserinfoAssertion = e.IDTokenUserinfoAssertion
wm.ClockSkew = e.ClockSkew
wm.AdditionalOrigins = e.AdditionalOrigins
}
func (wm *OIDCApplicationWriteModel) appendChangeOIDCEvent(e *project.OIDCConfigChangedEvent) {
@@ -193,6 +195,9 @@ func (wm *OIDCApplicationWriteModel) appendChangeOIDCEvent(e *project.OIDCConfig
if e.ClockSkew != nil {
wm.ClockSkew = *e.ClockSkew
}
if e.AdditionalOrigins != nil {
wm.AdditionalOrigins = *e.AdditionalOrigins
}
}
func (wm *OIDCApplicationWriteModel) Query() *eventstore.SearchQueryBuilder {
@@ -229,6 +234,7 @@ func (wm *OIDCApplicationWriteModel) NewChangedEvent(
idTokenRoleAssertion,
idTokenUserinfoAssertion bool,
clockSkew time.Duration,
additionalOrigins []string,
) (*project.OIDCConfigChangedEvent, bool, error) {
changes := make([]project.OIDCConfigChanges, 0)
var err error
@@ -272,6 +278,9 @@ func (wm *OIDCApplicationWriteModel) NewChangedEvent(
if wm.ClockSkew != clockSkew {
changes = append(changes, project.ChangeClockSkew(clockSkew))
}
if !reflect.DeepEqual(wm.AdditionalOrigins, additionalOrigins) {
changes = append(changes, project.ChangeAdditionalOrigins(additionalOrigins))
}
if len(changes) == 0 {
return nil, false, nil
}

View File

@@ -151,7 +151,8 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
true,
true,
true,
time.Second*1),
time.Second*1,
[]string{"https://sub.test.ch"}),
),
},
uniqueConstraintsFromEventConstraint(project.NewAddApplicationUniqueConstraint("app", "project1")),
@@ -180,6 +181,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
IDTokenRoleAssertion: true,
IDTokenUserinfoAssertion: true,
ClockSkew: time.Second * 1,
AdditionalOrigins: []string{"https://sub.test.ch"},
},
resourceOwner: "org1",
},
@@ -206,6 +208,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
IDTokenRoleAssertion: true,
IDTokenUserinfoAssertion: true,
ClockSkew: time.Second * 1,
AdditionalOrigins: []string{"https://sub.test.ch"},
State: domain.AppStateActive,
Compliance: &domain.Compliance{},
},
@@ -382,7 +385,8 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
true,
true,
true,
time.Second*1),
time.Second*1,
[]string{"https://sub.test.ch"}),
),
),
),
@@ -408,6 +412,7 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
IDTokenRoleAssertion: true,
IDTokenUserinfoAssertion: true,
ClockSkew: time.Second * 1,
AdditionalOrigins: []string{"https://sub.test.ch"},
},
resourceOwner: "org1",
},
@@ -451,7 +456,8 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
true,
true,
true,
time.Second*1),
time.Second*1,
[]string{"https://sub.test.ch"}),
),
),
expectPush(
@@ -487,6 +493,7 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
IDTokenRoleAssertion: false,
IDTokenUserinfoAssertion: false,
ClockSkew: time.Second * 2,
AdditionalOrigins: []string{"https://sub.test.ch"},
},
resourceOwner: "org1",
},
@@ -512,6 +519,7 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
IDTokenRoleAssertion: false,
IDTokenUserinfoAssertion: false,
ClockSkew: time.Second * 2,
AdditionalOrigins: []string{"https://sub.test.ch"},
Compliance: &domain.Compliance{},
State: domain.AppStateActive,
},
@@ -645,7 +653,8 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
true,
true,
true,
time.Second*1),
time.Second*1,
[]string{"https://sub.test.ch"}),
),
),
expectPush(
@@ -695,6 +704,7 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
IDTokenRoleAssertion: true,
IDTokenUserinfoAssertion: true,
ClockSkew: time.Second * 1,
AdditionalOrigins: []string{"https://sub.test.ch"},
State: domain.AppStateActive,
},
},

View File

@@ -51,6 +51,7 @@ func oidcWriteModelToOIDCConfig(writeModel *OIDCApplicationWriteModel) *domain.O
IDTokenRoleAssertion: writeModel.IDTokenRoleAssertion,
IDTokenUserinfoAssertion: writeModel.IDTokenUserinfoAssertion,
ClockSkew: writeModel.ClockSkew,
AdditionalOrigins: writeModel.AdditionalOrigins,
}
}

View File

@@ -4,6 +4,7 @@ import (
"strings"
"time"
http_util "github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/eventstore/v1/models"
)
@@ -43,6 +44,7 @@ type OIDCApp struct {
IDTokenRoleAssertion bool
IDTokenUserinfoAssertion bool
ClockSkew time.Duration
AdditionalOrigins []string
State AppState
}
@@ -119,7 +121,7 @@ const (
)
func (a *OIDCApp) IsValid() bool {
if a.ClockSkew > time.Second*5 || a.ClockSkew < time.Second*0 {
if a.ClockSkew > time.Second*5 || a.ClockSkew < time.Second*0 || !a.OriginsValid() {
return false
}
grantTypes := a.getRequiredGrantTypes()
@@ -135,6 +137,15 @@ func (a *OIDCApp) IsValid() bool {
return true
}
func (a *OIDCApp) OriginsValid() bool {
for _, origin := range a.AdditionalOrigins {
if !http_util.IsOrigin(origin) {
return false
}
}
return true
}
func (a *OIDCApp) getRequiredGrantTypes() []OIDCGrantType {
grantTypes := make([]OIDCGrantType, 0)
implicit := false

View File

@@ -1,9 +1,10 @@
package domain
import (
"github.com/caos/zitadel/internal/eventstore/v1/models"
"testing"
"time"
"github.com/caos/zitadel/internal/eventstore/v1/models"
)
func TestApplicationValid(t *testing.T) {
@@ -160,6 +161,20 @@ func TestApplicationValid(t *testing.T) {
},
result: true,
},
{
name: "invalid oidc application: invalid origin",
args: args{
app: &OIDCApp{
ObjectRoot: models.ObjectRoot{AggregateID: "AggregateID"},
AppID: "AppID",
AppName: "Name",
ResponseTypes: []OIDCResponseType{OIDCResponseTypeCode, OIDCResponseTypeIDToken, OIDCResponseTypeIDTokenToken},
GrantTypes: []OIDCGrantType{OIDCGrantTypeAuthorizationCode, OIDCGrantTypeImplicit},
AdditionalOrigins: []string{"https://test.com/test"},
},
},
result: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@@ -30,6 +30,7 @@ type ApplicationView struct {
ComplianceProblems []string
DevMode bool
OriginAllowList []string
AdditionalOrigins []string
AccessTokenType OIDCTokenType
IDTokenRoleAssertion bool
AccessTokenRoleAssertion bool

View File

@@ -45,6 +45,7 @@ type ApplicationView struct {
ComplianceProblems pq.StringArray `json:"-" gorm:"column:compliance_problems"`
DevMode bool `json:"devMode" gorm:"column:dev_mode"`
OriginAllowList pq.StringArray `json:"-" gorm:"column:origin_allow_list"`
AdditionalOrigins pq.StringArray `json:"additionalOrigins" gorm:"column:additional_origins"`
AccessTokenType int32 `json:"accessTokenType" gorm:"column:access_token_type"`
AccessTokenRoleAssertion bool `json:"accessTokenRoleAssertion" gorm:"column:access_token_role_assertion"`
IDTokenRoleAssertion bool `json:"idTokenRoleAssertion" gorm:"column:id_token_role_assertion"`
@@ -79,6 +80,7 @@ func ApplicationViewToModel(app *ApplicationView) *model.ApplicationView {
ComplianceProblems: app.ComplianceProblems,
DevMode: app.DevMode,
OriginAllowList: app.OriginAllowList,
AdditionalOrigins: app.AdditionalOrigins,
AccessTokenType: model.OIDCTokenType(app.AccessTokenType),
AccessTokenRoleAssertion: app.AccessTokenRoleAssertion,
IDTokenRoleAssertion: app.IDTokenRoleAssertion,
@@ -213,6 +215,11 @@ func (a *ApplicationView) setOriginAllowList() error {
allowList = append(allowList, origin)
}
}
for _, origin := range a.AdditionalOrigins {
if !http_util.IsOriginAllowed(allowList, origin) {
allowList = append(allowList, origin)
}
}
a.OriginAllowList = allowList
return nil
}

View File

@@ -3,12 +3,12 @@ package project
import (
"context"
"encoding/json"
"github.com/caos/zitadel/internal/eventstore"
"time"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/repository"
)
@@ -39,6 +39,7 @@ type OIDCConfigAddedEvent struct {
IDTokenRoleAssertion bool `json:"idTokenRoleAssertion,omitempty"`
IDTokenUserinfoAssertion bool `json:"idTokenUserinfoAssertion,omitempty"`
ClockSkew time.Duration `json:"clockSkew,omitempty"`
AdditionalOrigins []string `json:"additionalOrigins,omitempty"`
}
func (e *OIDCConfigAddedEvent) Data() interface{} {
@@ -68,6 +69,7 @@ func NewOIDCConfigAddedEvent(
idTokenRoleAssertion bool,
idTokenUserinfoAssertion bool,
clockSkew time.Duration,
additionalOrigins []string,
) *OIDCConfigAddedEvent {
return &OIDCConfigAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
@@ -91,6 +93,7 @@ func NewOIDCConfigAddedEvent(
IDTokenRoleAssertion: idTokenRoleAssertion,
IDTokenUserinfoAssertion: idTokenUserinfoAssertion,
ClockSkew: clockSkew,
AdditionalOrigins: additionalOrigins,
}
}
@@ -124,6 +127,7 @@ type OIDCConfigChangedEvent struct {
IDTokenRoleAssertion *bool `json:"idTokenRoleAssertion,omitempty"`
IDTokenUserinfoAssertion *bool `json:"idTokenUserinfoAssertion,omitempty"`
ClockSkew *time.Duration `json:"clockSkew,omitempty"`
AdditionalOrigins *[]string `json:"additionalOrigins,omitempty"`
}
func (e *OIDCConfigChangedEvent) Data() interface{} {
@@ -238,6 +242,12 @@ func ChangeClockSkew(clockSkew time.Duration) func(event *OIDCConfigChangedEvent
}
}
func ChangeAdditionalOrigins(additionalOrigins []string) func(event *OIDCConfigChangedEvent) {
return func(e *OIDCConfigChangedEvent) {
e.AdditionalOrigins = &additionalOrigins
}
}
func OIDCConfigChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e := &OIDCConfigChangedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),