zitadel/internal/api/oidc/integration_test/keys_test.go
Tim Möhlmann 4413efd82c
chore: remove parallel running in integration tests (#8904)
# Which Problems Are Solved

Integration tests are flaky due to eventual consistency.

# How the Problems Are Solved

Remove t.Parallel so that less concurrent requests on multiple instance
happen. This allows the projections to catch up more easily.

# Additional Changes

- none

# Additional Context

- none
2024-11-27 15:32:13 +01:00

122 lines
3.6 KiB
Go

//go:build integration
package oidc_test
import (
"crypto/rsa"
"encoding/json"
"net/http"
"testing"
"time"
"github.com/go-jose/go-jose/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v3/pkg/client"
"github.com/zitadel/oidc/v3/pkg/oidc"
"google.golang.org/protobuf/proto"
http_util "github.com/zitadel/zitadel/internal/api/http"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/integration"
"github.com/zitadel/zitadel/pkg/grpc/feature/v2"
oidc_pb "github.com/zitadel/zitadel/pkg/grpc/oidc/v2"
)
func TestServer_Keys(t *testing.T) {
instance := integration.NewInstance(CTX)
ctxLogin := instance.WithAuthorization(CTX, integration.UserTypeLogin)
clientID, _ := createClient(t, instance)
authRequestID := createAuthRequest(t, instance, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
instance.RegisterUserPasskey(instance.WithAuthorization(CTX, integration.UserTypeOrgOwner), instance.AdminUserID)
sessionID, sessionToken, _, _ := instance.CreateVerifiedWebAuthNSession(t, ctxLogin, instance.AdminUserID)
linkResp, err := instance.Client.OIDCv2.CreateCallback(ctxLogin, &oidc_pb.CreateCallbackRequest{
AuthRequestId: authRequestID,
CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
Session: &oidc_pb.Session{
SessionId: sessionID,
SessionToken: sessionToken,
},
},
})
require.NoError(t, err)
// code exchange so we are sure there is 1 legacy key pair.
code := assertCodeResponse(t, linkResp.GetCallbackUrl())
_, err = exchangeTokens(t, instance, clientID, code, redirectURI)
require.NoError(t, err)
issuer := http_util.BuildHTTP(instance.Domain, instance.Config.Port, instance.Config.Secure)
discovery, err := client.Discover(CTX, issuer, http.DefaultClient)
require.NoError(t, err)
tests := []struct {
name string
webKeyFeature bool
wantLen int
}{
{
name: "legacy only",
webKeyFeature: false,
wantLen: 1,
},
{
name: "webkeys with legacy",
webKeyFeature: true,
wantLen: 3, // 1 legacy + 2 created by enabling feature flag
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ensureWebKeyFeature(t, instance, tt.webKeyFeature)
assert.EventuallyWithT(t, func(ttt *assert.CollectT) {
resp, err := http.Get(discovery.JwksURI)
require.NoError(ttt, err)
require.Equal(ttt, resp.StatusCode, http.StatusOK)
defer resp.Body.Close()
got := new(jose.JSONWebKeySet)
err = json.NewDecoder(resp.Body).Decode(got)
require.NoError(ttt, err)
assert.Len(t, got.Keys, tt.wantLen)
for _, key := range got.Keys {
_, ok := key.Key.(*rsa.PublicKey)
require.True(ttt, ok)
require.NotEmpty(ttt, key.KeyID)
require.Equal(ttt, key.Algorithm, string(jose.RS256))
require.Equal(ttt, key.Use, crypto.KeyUsageSigning.String())
}
cacheControl := resp.Header.Get("cache-control")
if tt.webKeyFeature {
require.Equal(ttt, "max-age=300, must-revalidate", cacheControl)
return
}
require.Equal(ttt, "no-store", cacheControl)
}, time.Minute, time.Second/10)
})
}
}
func ensureWebKeyFeature(t *testing.T, instance *integration.Instance, set bool) {
ctxIam := instance.WithAuthorization(CTX, integration.UserTypeIAMOwner)
_, err := instance.Client.FeatureV2.SetInstanceFeatures(ctxIam, &feature.SetInstanceFeaturesRequest{
WebKey: proto.Bool(set),
})
require.NoError(t, err)
t.Cleanup(func() {
_, err := instance.Client.FeatureV2.SetInstanceFeatures(ctxIam, &feature.SetInstanceFeaturesRequest{
WebKey: proto.Bool(false),
})
require.NoError(t, err)
})
}