fix(oidc): enable webkey feature by default (#10683)

# Which Problems Are Solved

When the webkey feature flag was not enabled before an upgrade to v4,
all JWT tokens became invalid.
This created a couple of issues:

- All users with JWT access tokens are logged-out
- Clients that are unable to refresh keys based on key ID break
- id_token_hint could no longer be validated.

# How the Problems Are Solved

Force-enable the webkey feature on the v3 version, so that the upgrade
path is cleaner. Sessions now have time to role-over to the new keys
before initiating the upgrade to v4.

# Additional Changes

- none

# Additional Context

- Related https://github.com/zitadel/zitadel/issues/10673

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Tim Möhlmann
2025-09-10 08:53:29 +03:00
committed by GitHub
parent 330928f8b5
commit ca510c52dd
4 changed files with 26 additions and 23 deletions

View File

@@ -34,7 +34,7 @@ func TestMain(m *testing.M) {
}
func TestServer_Feature_Disabled(t *testing.T) {
instance, iamCtx, _ := createInstance(t, false)
instance, iamCtx, _ := createInstance(t, true)
client := instance.Client.WebKeyV2Beta
t.Run("CreateWebKey", func(t *testing.T) {
@@ -60,7 +60,7 @@ func TestServer_Feature_Disabled(t *testing.T) {
}
func TestServer_ListWebKeys(t *testing.T) {
instance, iamCtx, creationDate := createInstance(t, true)
instance, iamCtx, creationDate := createInstance(t, false)
// After the feature is first enabled, we can expect 2 generated keys with the default config.
checkWebKeyListState(iamCtx, t, instance, 2, "", &webkey.WebKey_Rsa{
Rsa: &webkey.RSA{
@@ -71,7 +71,7 @@ func TestServer_ListWebKeys(t *testing.T) {
}
func TestServer_CreateWebKey(t *testing.T) {
instance, iamCtx, creationDate := createInstance(t, true)
instance, iamCtx, creationDate := createInstance(t, false)
client := instance.Client.WebKeyV2Beta
_, err := client.CreateWebKey(iamCtx, &webkey.CreateWebKeyRequest{
@@ -93,7 +93,7 @@ func TestServer_CreateWebKey(t *testing.T) {
}
func TestServer_ActivateWebKey(t *testing.T) {
instance, iamCtx, creationDate := createInstance(t, true)
instance, iamCtx, creationDate := createInstance(t, false)
client := instance.Client.WebKeyV2Beta
resp, err := client.CreateWebKey(iamCtx, &webkey.CreateWebKeyRequest{
@@ -120,7 +120,7 @@ func TestServer_ActivateWebKey(t *testing.T) {
}
func TestServer_DeleteWebKey(t *testing.T) {
instance, iamCtx, creationDate := createInstance(t, true)
instance, iamCtx, creationDate := createInstance(t, false)
client := instance.Client.WebKeyV2Beta
keyIDs := make([]string, 2)
@@ -197,14 +197,14 @@ func TestServer_DeleteWebKey(t *testing.T) {
}, creationDate)
}
func createInstance(t *testing.T, enableFeature bool) (*integration.Instance, context.Context, *timestamppb.Timestamp) {
func createInstance(t *testing.T, disableFeature bool) (*integration.Instance, context.Context, *timestamppb.Timestamp) {
instance := integration.NewInstance(CTX)
creationDate := timestamppb.Now()
creationDate := instance.Instance.GetDetails().GetCreationDate()
iamCTX := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
if enableFeature {
if disableFeature {
_, err := instance.Client.FeatureV2.SetInstanceFeatures(iamCTX, &feature.SetInstanceFeaturesRequest{
WebKey: proto.Bool(true),
WebKey: proto.Bool(false),
})
require.NoError(t, err)
}
@@ -212,11 +212,11 @@ func createInstance(t *testing.T, enableFeature bool) (*integration.Instance, co
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(iamCTX, time.Minute)
assert.EventuallyWithT(t, func(collect *assert.CollectT) {
resp, err := instance.Client.WebKeyV2Beta.ListWebKeys(iamCTX, &webkey.ListWebKeysRequest{})
if enableFeature {
if disableFeature {
assert.Error(collect, err)
} else {
assert.NoError(collect, err)
assert.Len(collect, resp.GetWebKeys(), 2)
} else {
assert.Error(collect, err)
}
}, retryDuration, tick)
@@ -244,8 +244,8 @@ func checkWebKeyListState(ctx context.Context, t *testing.T, instance *integrati
now := time.Now()
var gotActiveKeyID string
for _, key := range list {
assert.WithinRange(collect, key.GetCreationDate().AsTime(), now.Add(-time.Minute), now.Add(time.Minute))
assert.WithinRange(collect, key.GetChangeDate().AsTime(), now.Add(-time.Minute), now.Add(time.Minute))
assert.WithinRange(collect, key.GetCreationDate().AsTime(), creationDate.AsTime(), now.Add(time.Minute))
assert.WithinRange(collect, key.GetChangeDate().AsTime(), creationDate.AsTime(), now.Add(time.Minute))
assert.NotEqual(collect, webkey.State_STATE_UNSPECIFIED, key.GetState())
assert.NotEqual(collect, webkey.State_STATE_REMOVED, key.GetState())
assert.Equal(collect, config, key.GetKey())