diff --git a/console/package.json b/console/package.json
index 260b9aee7..947de2dda 100644
--- a/console/package.json
+++ b/console/package.json
@@ -69,4 +69,4 @@
"tslint": "~6.1.3",
"typescript": "^4.0.7"
}
-}
+}
\ No newline at end of file
diff --git a/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.html b/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.html
new file mode 100644
index 000000000..448b4f4eb
--- /dev/null
+++ b/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.html
@@ -0,0 +1,28 @@
+
+
+
+
+ {{uri}}
+
+
+
+
+
+
+
+
+
+ {{'APP.OIDC.REDIRECTNOTVALID' | translate}}
\ No newline at end of file
diff --git a/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.scss b/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.scss
new file mode 100644
index 000000000..fa3bade76
--- /dev/null
+++ b/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.scss
@@ -0,0 +1,62 @@
+.form {
+ display: flex;
+ align-items: flex-end;
+ min-width: 320px;
+
+ .formfield {
+ flex: 1;
+ }
+
+ button {
+ margin-bottom: 14px;
+ margin-right: -.5rem;
+ }
+}
+
+.uri-list {
+ margin: 0 .5rem;
+ width: 100%;
+
+ .uri-line {
+ display: flex;
+ align-items: center;
+
+ .uri {
+ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+ font-size: 14px;
+ }
+
+ .fill-space {
+ flex: 1;
+ }
+
+ i.green {
+ font-size: 1rem;
+ line-height: 35px;
+ height: 30px;
+ }
+
+ i.red {
+ font-size: 1.2rem;
+ }
+
+ .icon-button {
+ height: 30px;
+ line-height: 30px;
+
+ .icon {
+ font-size: 1rem !important;
+ }
+
+ &:not(:hover) {
+ color: var(--grey);
+ }
+ }
+ }
+}
+
+.error {
+ font-size: 13px;
+ color: #f44336;
+ margin: 0 .5rem 1.5rem .5rem;
+}
diff --git a/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.spec.ts b/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.spec.ts
new file mode 100644
index 000000000..ae36ab6fd
--- /dev/null
+++ b/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AdditionalOriginsComponent } from './additional-origins.component';
+
+describe('AdditionalOriginsComponent', () => {
+ let component: AdditionalOriginsComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [AdditionalOriginsComponent],
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AdditionalOriginsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.ts b/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.ts
new file mode 100644
index 000000000..8fcd38c99
--- /dev/null
+++ b/console/src/app/pages/projects/apps/additional-origins/additional-origins.component.ts
@@ -0,0 +1,56 @@
+import { Component, EventEmitter, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
+import { FormControl } from '@angular/forms';
+import { Observable, Subscription } from 'rxjs';
+
+@Component({
+ selector: 'cnsl-additional-origins',
+ templateUrl: './additional-origins.component.html',
+ styleUrls: ['./additional-origins.component.scss'],
+})
+export class AdditionalOriginsComponent implements OnInit, OnDestroy {
+ @Input() title: string = '';
+ @Input() canWrite: boolean = false;
+ @Input() public urisList: string[] = [];
+ @Input() public redirectControl: FormControl = new FormControl({ value: '', disabled: true });
+ @Input() public changedUris: EventEmitter = new EventEmitter();
+ @Input() public getValues: Observable = new Observable();
+ public placeholder: string = ' "://" [ ":" ]';
+
+ @ViewChild('originInput') input!: any;
+ private sub: Subscription = new Subscription();
+
+ constructor() { }
+
+ ngOnInit(): void {
+ if (this.canWrite) {
+ this.redirectControl.enable();
+ }
+
+ this.sub = this.getValues.subscribe(() => {
+ this.add(this.input.nativeElement);
+ });
+ }
+
+ ngOnDestroy(): void {
+ this.sub.unsubscribe();
+ }
+
+ public add(input: any): void {
+ if (this.redirectControl.valid) {
+ if (input.value !== '' && input.value !== ' ' && input.value !== '/') {
+ this.urisList.push(input.value);
+ }
+ if (input) {
+ input.value = '';
+ }
+ }
+ }
+
+ public remove(redirect: any): void {
+ const index = this.urisList.indexOf(redirect);
+
+ if (index >= 0) {
+ this.urisList.splice(index, 1);
+ }
+ }
+}
diff --git a/console/src/app/pages/projects/apps/app-detail/app-detail.component.html b/console/src/app/pages/projects/apps/app-detail/app-detail.component.html
index af0556d90..a6251c47a 100644
--- a/console/src/app/pages/projects/apps/app-detail/app-detail.component.html
+++ b/console/src/app/pages/projects/apps/app-detail/app-detail.component.html
@@ -118,7 +118,6 @@
{{'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate}}
-
+
+
+
+
+
{{'APP.ADDITIONALORIGINS' | translate}}
+
+
+
+ {{'APP.ADDITIONALORIGINSDESC' | translate}}
+
+
+
+
+
+
duration.lte.nanos: 0
duration.gte.seconds: 0
duration.gte.nanos: 0
|
+| additional_origins | repeated string | - | |
@@ -5194,6 +5195,7 @@ This is an empty request
| id_token_role_assertion | bool | - | |
| id_token_userinfo_assertion | bool | - | |
| clock_skew | google.protobuf.Duration | - | duration.lte.seconds: 5
duration.lte.nanos: 0
duration.gte.seconds: 0
duration.gte.nanos: 0
|
+| additional_origins | repeated string | - | |
diff --git a/internal/api/grpc/management/project_application_converter.go b/internal/api/grpc/management/project_application_converter.go
index e38ee5157..516bae58e 100644
--- a/internal/api/grpc/management/project_application_converter.go
+++ b/internal/api/grpc/management/project_application_converter.go
@@ -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,
}
}
diff --git a/internal/api/grpc/project/application.go b/internal/api/grpc/project/application.go
index 07f1b60f0..efcf57689 100644
--- a/internal/api/grpc/project/application.go
+++ b/internal/api/grpc/project/application.go
@@ -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,
},
}
}
diff --git a/internal/api/http/origin.go b/internal/api/http/origin.go
index 44f222790..62c6967bd 100644
--- a/internal/api/http/origin.go
+++ b/internal/api/http/origin.go
@@ -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 == ""
+}
diff --git a/internal/command/project_application_oidc.go b/internal/command/project_application_oidc.go
index 540c69eea..145340171 100644
--- a/internal/command/project_application_oidc.go
+++ b/internal/command/project_application_oidc.go
@@ -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
}
diff --git a/internal/command/project_application_oidc_model.go b/internal/command/project_application_oidc_model.go
index 2a39778c9..7b9ac23df 100644
--- a/internal/command/project_application_oidc_model.go
+++ b/internal/command/project_application_oidc_model.go
@@ -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
}
diff --git a/internal/command/project_application_oidc_test.go b/internal/command/project_application_oidc_test.go
index f4079603b..b590cf6cb 100644
--- a/internal/command/project_application_oidc_test.go
+++ b/internal/command/project_application_oidc_test.go
@@ -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,
},
},
diff --git a/internal/command/project_converter.go b/internal/command/project_converter.go
index 220911c50..2aee9bb5c 100644
--- a/internal/command/project_converter.go
+++ b/internal/command/project_converter.go
@@ -51,6 +51,7 @@ func oidcWriteModelToOIDCConfig(writeModel *OIDCApplicationWriteModel) *domain.O
IDTokenRoleAssertion: writeModel.IDTokenRoleAssertion,
IDTokenUserinfoAssertion: writeModel.IDTokenUserinfoAssertion,
ClockSkew: writeModel.ClockSkew,
+ AdditionalOrigins: writeModel.AdditionalOrigins,
}
}
diff --git a/internal/domain/application_oidc.go b/internal/domain/application_oidc.go
index dc3b14470..fd67b9c6f 100644
--- a/internal/domain/application_oidc.go
+++ b/internal/domain/application_oidc.go
@@ -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
diff --git a/internal/domain/application_oidc_test.go b/internal/domain/application_oidc_test.go
index b2897764b..63aee9159 100644
--- a/internal/domain/application_oidc_test.go
+++ b/internal/domain/application_oidc_test.go
@@ -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) {
diff --git a/internal/project/model/application_view.go b/internal/project/model/application_view.go
index 37db1ebc2..20bfc2062 100644
--- a/internal/project/model/application_view.go
+++ b/internal/project/model/application_view.go
@@ -30,6 +30,7 @@ type ApplicationView struct {
ComplianceProblems []string
DevMode bool
OriginAllowList []string
+ AdditionalOrigins []string
AccessTokenType OIDCTokenType
IDTokenRoleAssertion bool
AccessTokenRoleAssertion bool
diff --git a/internal/project/repository/view/model/application.go b/internal/project/repository/view/model/application.go
index 5a5a3a836..4440c10ec 100644
--- a/internal/project/repository/view/model/application.go
+++ b/internal/project/repository/view/model/application.go
@@ -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
}
diff --git a/internal/repository/project/oidc_config.go b/internal/repository/project/oidc_config.go
index 2c2996799..acf67ddcb 100644
--- a/internal/repository/project/oidc_config.go
+++ b/internal/repository/project/oidc_config.go
@@ -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),
diff --git a/migrations/cockroach/V1.43__additional_origins.sql b/migrations/cockroach/V1.43__additional_origins.sql
new file mode 100644
index 000000000..0aac4c474
--- /dev/null
+++ b/migrations/cockroach/V1.43__additional_origins.sql
@@ -0,0 +1,3 @@
+ALTER TABLE auth.applications ADD COLUMN additional_origins TEXT ARRAY;
+ALTER TABLE authz.applications ADD COLUMN additional_origins TEXT ARRAY;
+ALTER TABLE management.applications ADD COLUMN additional_origins TEXT ARRAY;
\ No newline at end of file
diff --git a/proto/zitadel/app.proto b/proto/zitadel/app.proto
index 20d9093a4..312d3adbd 100644
--- a/proto/zitadel/app.proto
+++ b/proto/zitadel/app.proto
@@ -65,7 +65,7 @@ message AppNameQuery {
message OIDCConfig {
repeated string redirect_uris = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
- example: "[\"console.zitadel.ch/authorized\"]";
+ example: "[\"https://console.zitadel.ch/auth/callback\"]";
description: "Callback URI of the authorization request where the code or tokens will be sent to";
}
];
@@ -103,7 +103,7 @@ message OIDCConfig {
];
repeated string post_logout_redirect_uris = 8 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
- example: "[\"console.zitadel.ch/logout\"]";
+ example: "[\"https://console.zitadel.ch/logout\"]";
description: "ZITADEL will redirect to this link after a successful logout";
}
];
@@ -154,6 +154,18 @@ message OIDCConfig {
// max: "5s";
}
];
+ repeated string additional_origins = 18 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ example: "[\"https://console.zitadel.ch/auth/callback\"]";
+ description: "additional origins (other than the redirect_uris) from where the api can be used";
+ }
+ ];
+ repeated string allowed_origins = 19 [
+ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
+ example: "[\"https://console.zitadel.ch/auth/callback\"]";
+ description: "all allowed origins from where the api can be used";
+ }
+ ];
}
enum OIDCResponseType {
diff --git a/proto/zitadel/management.proto b/proto/zitadel/management.proto
index 83f7c470f..f8d241298 100644
--- a/proto/zitadel/management.proto
+++ b/proto/zitadel/management.proto
@@ -2953,6 +2953,7 @@ message AddOIDCAppRequest {
bool id_token_role_assertion = 13;
bool id_token_userinfo_assertion = 14;
google.protobuf.Duration clock_skew = 15 [(validate.rules).duration = {gte: {}, lte: {seconds: 5}}];
+ repeated string additional_origins = 16;
}
message AddOIDCAppResponse {
@@ -3023,6 +3024,7 @@ message UpdateOIDCAppConfigRequest {
bool id_token_role_assertion = 12;
bool id_token_userinfo_assertion = 13;
google.protobuf.Duration clock_skew = 14 [(validate.rules).duration = {gte: {}, lte: {seconds: 5}}];
+ repeated string additional_origins = 15;
}
message UpdateOIDCAppConfigResponse {