mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-09 07:35:13 +00:00
feat(oidc): move back-channel logout from beta to GA (#11493)
# Which Problems Are Solved This PR marks the OIDC Back-Channel Logout as general available (GA). # How the Problems Are Solved - API: - deprecated the feature toggle (to prevent breaking changes) in v2beta and v2 API - removed all related event logic and updated the projection iteration - removed the toggle usage for back-channel logout - removed related translations - Management Console: - removed the feature toggle and its translations - Docs: - removed all beta labels and feature toggle notes # Additional Changes none # Additional Context - closes #11277 - requires backport to v4.x
This commit is contained in:
@@ -19,7 +19,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/feature"
|
||||
"github.com/zitadel/zitadel/internal/id"
|
||||
"github.com/zitadel/zitadel/internal/id/mock"
|
||||
"github.com/zitadel/zitadel/internal/repository/deviceauth"
|
||||
@@ -1088,7 +1087,7 @@ func TestCommands_CreateOIDCSessionFromDeviceAuth(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "approved with backChannelLogout (feature enabled), success",
|
||||
name: "approved with backChannelLogout, success",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
@@ -1167,9 +1166,7 @@ func TestCommands_CreateOIDCSessionFromDeviceAuth(t *testing.T) {
|
||||
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
authz.WithFeatures(ctx, feature.Features{
|
||||
EnableBackChannelLogout: true,
|
||||
}),
|
||||
ctx,
|
||||
"123",
|
||||
"backChannelLogoutURI",
|
||||
},
|
||||
|
||||
@@ -136,7 +136,6 @@ type InstanceSetupFeatures struct {
|
||||
ImprovedPerformance []feature.ImprovedPerformanceType
|
||||
DebugOIDCParentError *bool
|
||||
OIDCSingleV1SessionTermination *bool
|
||||
EnableBackChannelLogout *bool
|
||||
LoginV2 *InstanceSetupFeatureLoginV2
|
||||
PermissionCheckV2 *bool
|
||||
ManagementConsoleUseV2UserApi *bool
|
||||
@@ -169,7 +168,6 @@ func (f *InstanceSetupFeatures) ToInstanceFeatures() (_ *InstanceFeatures, err e
|
||||
ImprovedPerformance: f.ImprovedPerformance,
|
||||
DebugOIDCParentError: f.DebugOIDCParentError,
|
||||
OIDCSingleV1SessionTermination: f.OIDCSingleV1SessionTermination,
|
||||
EnableBackChannelLogout: f.EnableBackChannelLogout,
|
||||
LoginV2: loginV2,
|
||||
PermissionCheckV2: f.PermissionCheckV2,
|
||||
ManagementConsoleUseV2UserApi: f.ManagementConsoleUseV2UserApi,
|
||||
|
||||
@@ -18,7 +18,6 @@ type InstanceFeatures struct {
|
||||
ImprovedPerformance []feature.ImprovedPerformanceType
|
||||
DebugOIDCParentError *bool
|
||||
OIDCSingleV1SessionTermination *bool
|
||||
EnableBackChannelLogout *bool
|
||||
LoginV2 *feature.LoginV2
|
||||
PermissionCheckV2 *bool
|
||||
ManagementConsoleUseV2UserApi *bool
|
||||
@@ -32,7 +31,6 @@ func (m *InstanceFeatures) isEmpty() bool {
|
||||
m.ImprovedPerformance == nil &&
|
||||
m.DebugOIDCParentError == nil &&
|
||||
m.OIDCSingleV1SessionTermination == nil &&
|
||||
m.EnableBackChannelLogout == nil &&
|
||||
m.LoginV2 == nil &&
|
||||
m.PermissionCheckV2 == nil &&
|
||||
m.ManagementConsoleUseV2UserApi == nil &&
|
||||
|
||||
@@ -71,7 +71,6 @@ func (m *InstanceFeaturesWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
feature_v2.InstanceImprovedPerformanceEventType,
|
||||
feature_v2.InstanceDebugOIDCParentErrorEventType,
|
||||
feature_v2.InstanceOIDCSingleV1SessionTerminationEventType,
|
||||
feature_v2.InstanceEnableBackChannelLogout,
|
||||
feature_v2.InstanceLoginVersion,
|
||||
feature_v2.InstancePermissionCheckV2,
|
||||
feature_v2.InstanceManagementConsoleUseV2UserApi,
|
||||
@@ -103,9 +102,6 @@ func reduceInstanceFeature(features *InstanceFeatures, key feature.Key, value an
|
||||
case feature.KeyOIDCSingleV1SessionTermination:
|
||||
v := value.(bool)
|
||||
features.OIDCSingleV1SessionTermination = &v
|
||||
case feature.KeyEnableBackChannelLogout:
|
||||
v := value.(bool)
|
||||
features.EnableBackChannelLogout = &v
|
||||
case feature.KeyLoginV2:
|
||||
features.LoginV2 = value.(*feature.LoginV2)
|
||||
case feature.KeyPermissionCheckV2:
|
||||
@@ -128,7 +124,6 @@ func (wm *InstanceFeaturesWriteModel) setCommands(ctx context.Context, f *Instan
|
||||
cmds = appendFeatureSliceUpdate(ctx, cmds, aggregate, wm.ImprovedPerformance, f.ImprovedPerformance, feature_v2.InstanceImprovedPerformanceEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.DebugOIDCParentError, f.DebugOIDCParentError, feature_v2.InstanceDebugOIDCParentErrorEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.OIDCSingleV1SessionTermination, f.OIDCSingleV1SessionTermination, feature_v2.InstanceOIDCSingleV1SessionTerminationEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.EnableBackChannelLogout, f.EnableBackChannelLogout, feature_v2.InstanceEnableBackChannelLogout)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.LoginV2, f.LoginV2, feature_v2.InstanceLoginVersion)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.PermissionCheckV2, f.PermissionCheckV2, feature_v2.InstancePermissionCheckV2)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.ManagementConsoleUseV2UserApi, f.ManagementConsoleUseV2UserApi, feature_v2.InstanceManagementConsoleUseV2UserApi)
|
||||
|
||||
@@ -74,15 +74,6 @@ func Test_reduceInstanceFeature(t *testing.T) {
|
||||
},
|
||||
expected: &InstanceFeatures{OIDCSingleV1SessionTermination: gu.Ptr(true)},
|
||||
},
|
||||
{
|
||||
name: "enable back channel logout",
|
||||
args: args{
|
||||
features: &InstanceFeatures{},
|
||||
key: feature.KeyEnableBackChannelLogout,
|
||||
value: true,
|
||||
},
|
||||
expected: &InstanceFeatures{EnableBackChannelLogout: gu.Ptr(true)},
|
||||
},
|
||||
{
|
||||
name: "login v2",
|
||||
args: args{
|
||||
|
||||
@@ -1779,7 +1779,6 @@ func TestInstanceSetupFeatures_ToInstanceFeatures(t *testing.T) {
|
||||
ImprovedPerformance []feature.ImprovedPerformanceType
|
||||
DebugOIDCParentError *bool
|
||||
OIDCSingleV1SessionTermination *bool
|
||||
EnableBackChannelLogout *bool
|
||||
LoginV2 *InstanceSetupFeatureLoginV2
|
||||
PermissionCheckV2 *bool
|
||||
ManagementConsoleUseV2UserApi *bool
|
||||
@@ -1808,7 +1807,6 @@ func TestInstanceSetupFeatures_ToInstanceFeatures(t *testing.T) {
|
||||
ImprovedPerformance: []feature.ImprovedPerformanceType{feature.ImprovedPerformanceTypeOrgDomainVerified},
|
||||
DebugOIDCParentError: gu.Ptr(true),
|
||||
OIDCSingleV1SessionTermination: gu.Ptr(false),
|
||||
EnableBackChannelLogout: gu.Ptr(true),
|
||||
PermissionCheckV2: gu.Ptr(true),
|
||||
ManagementConsoleUseV2UserApi: gu.Ptr(false),
|
||||
EnableRelationalTables: gu.Ptr(true),
|
||||
@@ -1819,7 +1817,6 @@ func TestInstanceSetupFeatures_ToInstanceFeatures(t *testing.T) {
|
||||
ImprovedPerformance: []feature.ImprovedPerformanceType{feature.ImprovedPerformanceTypeOrgDomainVerified},
|
||||
DebugOIDCParentError: gu.Ptr(true),
|
||||
OIDCSingleV1SessionTermination: gu.Ptr(false),
|
||||
EnableBackChannelLogout: gu.Ptr(true),
|
||||
LoginV2: nil,
|
||||
PermissionCheckV2: gu.Ptr(true),
|
||||
ManagementConsoleUseV2UserApi: gu.Ptr(false),
|
||||
@@ -1875,7 +1872,6 @@ func TestInstanceSetupFeatures_ToInstanceFeatures(t *testing.T) {
|
||||
ImprovedPerformance: tc.fields.ImprovedPerformance,
|
||||
DebugOIDCParentError: tc.fields.DebugOIDCParentError,
|
||||
OIDCSingleV1SessionTermination: tc.fields.OIDCSingleV1SessionTermination,
|
||||
EnableBackChannelLogout: tc.fields.EnableBackChannelLogout,
|
||||
LoginV2: tc.fields.LoginV2,
|
||||
PermissionCheckV2: tc.fields.PermissionCheckV2,
|
||||
ManagementConsoleUseV2UserApi: tc.fields.ManagementConsoleUseV2UserApi,
|
||||
|
||||
@@ -452,9 +452,6 @@ func (c *OIDCSessionEvents) RegisterLogout(ctx context.Context, sessionID, userI
|
||||
if sessionID == "" || backChannelLogoutURI == "" {
|
||||
return
|
||||
}
|
||||
if !authz.GetFeatures(ctx).EnableBackChannelLogout {
|
||||
return
|
||||
}
|
||||
|
||||
c.events = append(c.events, sessionlogout.NewBackChannelLogoutRegisteredEvent(
|
||||
ctx,
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/feature"
|
||||
"github.com/zitadel/zitadel/internal/id"
|
||||
"github.com/zitadel/zitadel/internal/id/mock"
|
||||
"github.com/zitadel/zitadel/internal/repository/authrequest"
|
||||
@@ -554,9 +553,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
|
||||
},
|
||||
args{
|
||||
|
||||
ctx: authz.WithFeatures(authz.WithInstanceID(context.Background(), "instanceID"), feature.Features{
|
||||
EnableBackChannelLogout: true,
|
||||
}),
|
||||
ctx: authz.WithInstanceID(context.Background(), "instanceID"),
|
||||
authRequestID: "V2_authRequestID",
|
||||
complianceCheck: mockAuthRequestComplianceChecker(nil),
|
||||
needRefreshToken: true,
|
||||
@@ -1333,104 +1330,6 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "with backChannelLogoutURI and sessionID",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
user.NewHumanAddedEvent(
|
||||
context.Background(),
|
||||
&user.NewAggregate("userID", "org1").Aggregate,
|
||||
"username",
|
||||
"firstname",
|
||||
"lastname",
|
||||
"nickname",
|
||||
"displayname",
|
||||
language.Afrikaans,
|
||||
domain.GenderUnspecified,
|
||||
"email",
|
||||
false,
|
||||
),
|
||||
),
|
||||
expectFilter(), // token lifetime
|
||||
expectPush(
|
||||
oidcsession.NewAddedEvent(context.Background(), &oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
|
||||
"userID", "org1", "sessionID", "clientID", []string{"audience"}, []string{"openid", "offline_access"},
|
||||
[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword}, testNow, "nonce", &language.Afrikaans,
|
||||
&domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{"foo": []string{"bar"}},
|
||||
},
|
||||
),
|
||||
oidcsession.NewAccessTokenAddedEvent(context.Background(),
|
||||
&oidcsession.NewAggregate("V2_oidcSessionID", "org1").Aggregate,
|
||||
"at_accessTokenID", []string{"openid", "offline_access"}, time.Hour, domain.TokenReasonAuthRequest,
|
||||
&domain.TokenActor{
|
||||
UserID: "user2",
|
||||
Issuer: "foo.com",
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
idGenerator: mock.NewIDGeneratorExpectIDs(t, "oidcSessionID", "accessTokenID"),
|
||||
defaultAccessTokenLifetime: time.Hour,
|
||||
defaultRefreshTokenLifetime: 7 * 24 * time.Hour,
|
||||
defaultRefreshTokenIdleLifetime: 24 * time.Hour,
|
||||
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "instanceID"),
|
||||
userID: "userID",
|
||||
resourceOwner: "org1",
|
||||
clientID: "clientID",
|
||||
backChannelLogoutURI: "backChannelLogoutURI",
|
||||
audience: []string{"audience"},
|
||||
scope: []string{"openid", "offline_access"},
|
||||
authMethods: []domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
|
||||
authTime: testNow,
|
||||
nonce: "nonce",
|
||||
preferredLanguage: &language.Afrikaans,
|
||||
userAgent: &domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{"foo": []string{"bar"}},
|
||||
},
|
||||
reason: domain.TokenReasonAuthRequest,
|
||||
actor: &domain.TokenActor{
|
||||
UserID: "user2",
|
||||
Issuer: "foo.com",
|
||||
},
|
||||
needRefreshToken: false,
|
||||
sessionID: "sessionID",
|
||||
},
|
||||
want: &OIDCSession{
|
||||
TokenID: "V2_oidcSessionID-at_accessTokenID",
|
||||
ClientID: "clientID",
|
||||
UserID: "userID",
|
||||
Audience: []string{"audience"},
|
||||
Expiration: time.Time{}.Add(time.Hour),
|
||||
Scope: []string{"openid", "offline_access"},
|
||||
AuthMethods: []domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
|
||||
AuthTime: testNow,
|
||||
Nonce: "nonce",
|
||||
PreferredLanguage: &language.Afrikaans,
|
||||
UserAgent: &domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{"foo": []string{"bar"}},
|
||||
},
|
||||
Reason: domain.TokenReasonAuthRequest,
|
||||
Actor: &domain.TokenActor{
|
||||
UserID: "user2",
|
||||
Issuer: "foo.com",
|
||||
},
|
||||
SessionID: "sessionID",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with backChannelLogoutURI and sessionID, backchannel logout enabled",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
@@ -1484,7 +1383,7 @@ func TestCommands_CreateOIDCSession(t *testing.T) {
|
||||
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithFeatures(authz.WithInstanceID(context.Background(), "instanceID"), feature.Features{EnableBackChannelLogout: true}),
|
||||
ctx: authz.WithInstanceID(context.Background(), "instanceID"),
|
||||
userID: "userID",
|
||||
resourceOwner: "org1",
|
||||
clientID: "clientID",
|
||||
|
||||
@@ -14,7 +14,6 @@ type SystemFeatures struct {
|
||||
UserSchema *bool
|
||||
ImprovedPerformance []feature.ImprovedPerformanceType
|
||||
OIDCSingleV1SessionTermination *bool
|
||||
EnableBackChannelLogout *bool
|
||||
LoginV2 *feature.LoginV2
|
||||
PermissionCheckV2 *bool
|
||||
EnableRelationalTables *bool
|
||||
@@ -26,7 +25,6 @@ func (m *SystemFeatures) isEmpty() bool {
|
||||
// nil check to allow unset improvements
|
||||
m.ImprovedPerformance == nil &&
|
||||
m.OIDCSingleV1SessionTermination == nil &&
|
||||
m.EnableBackChannelLogout == nil &&
|
||||
m.LoginV2 == nil &&
|
||||
m.PermissionCheckV2 == nil &&
|
||||
m.EnableRelationalTables == nil)
|
||||
|
||||
@@ -63,7 +63,6 @@ func (m *SystemFeaturesWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
feature_v2.SystemUserSchemaEventType,
|
||||
feature_v2.SystemImprovedPerformanceEventType,
|
||||
feature_v2.SystemOIDCSingleV1SessionTerminationEventType,
|
||||
feature_v2.SystemEnableBackChannelLogout,
|
||||
feature_v2.SystemLoginVersion,
|
||||
feature_v2.SystemPermissionCheckV2,
|
||||
feature_v2.SystemEnableRelationalTables,
|
||||
@@ -90,9 +89,6 @@ func reduceSystemFeature(features *SystemFeatures, key feature.Key, value any) {
|
||||
case feature.KeyOIDCSingleV1SessionTermination:
|
||||
v := value.(bool)
|
||||
features.OIDCSingleV1SessionTermination = &v
|
||||
case feature.KeyEnableBackChannelLogout:
|
||||
v := value.(bool)
|
||||
features.EnableBackChannelLogout = &v
|
||||
case feature.KeyLoginV2:
|
||||
features.LoginV2 = value.(*feature.LoginV2)
|
||||
case feature.KeyPermissionCheckV2:
|
||||
@@ -111,7 +107,6 @@ func (wm *SystemFeaturesWriteModel) setCommands(ctx context.Context, f *SystemFe
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.UserSchema, f.UserSchema, feature_v2.SystemUserSchemaEventType)
|
||||
cmds = appendFeatureSliceUpdate(ctx, cmds, aggregate, wm.ImprovedPerformance, f.ImprovedPerformance, feature_v2.SystemImprovedPerformanceEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.OIDCSingleV1SessionTermination, f.OIDCSingleV1SessionTermination, feature_v2.SystemOIDCSingleV1SessionTerminationEventType)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.EnableBackChannelLogout, f.EnableBackChannelLogout, feature_v2.SystemEnableBackChannelLogout)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.LoginV2, f.LoginV2, feature_v2.SystemLoginVersion)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.PermissionCheckV2, f.PermissionCheckV2, feature_v2.SystemPermissionCheckV2)
|
||||
cmds = appendFeatureUpdate(ctx, cmds, aggregate, wm.EnableRelationalTables, f.EnableRelationalTables, feature_v2.SystemEnableRelationalTables)
|
||||
|
||||
@@ -91,12 +91,12 @@ func TestCommands_SetSystemFeatures(t *testing.T) {
|
||||
expectPushFailed(io.ErrClosedPipe,
|
||||
feature_v2.NewSetEvent(
|
||||
context.Background(), aggregate,
|
||||
feature_v2.SystemEnableBackChannelLogout, true,
|
||||
feature_v2.SystemPermissionCheckV2, true,
|
||||
),
|
||||
),
|
||||
),
|
||||
args: args{context.Background(), &SystemFeatures{
|
||||
EnableBackChannelLogout: gu.Ptr(true),
|
||||
PermissionCheckV2: gu.Ptr(true),
|
||||
}},
|
||||
wantErr: io.ErrClosedPipe,
|
||||
},
|
||||
@@ -291,7 +291,6 @@ func TestSystemFeatures_isEmpty(t *testing.T) {
|
||||
{name: "UserSchema set", sysFeatures: &SystemFeatures{UserSchema: gu.Ptr(true)}, want: false},
|
||||
{name: "ImprovedPerformance set", sysFeatures: &SystemFeatures{ImprovedPerformance: []feature.ImprovedPerformanceType{}}, want: false},
|
||||
{name: "OIDCSingleV1SessionTermination set", sysFeatures: &SystemFeatures{OIDCSingleV1SessionTermination: gu.Ptr(true)}, want: false},
|
||||
{name: "EnableBackChannelLogout set", sysFeatures: &SystemFeatures{EnableBackChannelLogout: gu.Ptr(true)}, want: false},
|
||||
{name: "LoginV2 set", sysFeatures: &SystemFeatures{LoginV2: &feature.LoginV2{}}, want: false},
|
||||
{name: "PermissionCheckV2 set", sysFeatures: &SystemFeatures{PermissionCheckV2: gu.Ptr(true)}, want: false},
|
||||
{name: "EnableRelationalTables set", sysFeatures: &SystemFeatures{EnableRelationalTables: gu.Ptr(true)}, want: false},
|
||||
|
||||
Reference in New Issue
Block a user