zitadel/internal/api/oidc/integration_test/token_jwt_profile_test.go
Tim Möhlmann 4eaa3163b6
feat(storage): generic cache interface (#8628)
# Which Problems Are Solved

We identified the need of caching.
Currently we have a number of places where we use different ways of
caching, like go maps or LRU.
We might also want shared chaches in the future, like Redis-based or in
special SQL tables.

# How the Problems Are Solved

Define a generic Cache interface which allows different implementations.

- A noop implementation is provided and enabled as.
- An implementation using go maps is provided
  - disabled in defaults.yaml
  - enabled in integration tests
- Authz middleware instance objects are cached using the interface.

# Additional Changes

- Enabled integration test command raceflag
- Fix a race condition in the limits integration test client
- Fix a number of flaky integration tests. (Because zitadel is super
fast now!) 🎸 🚀

# Additional Context

Related to https://github.com/zitadel/zitadel/issues/8648
2024-09-25 21:40:21 +02:00

135 lines
4.1 KiB
Go

//go:build integration
package oidc_test
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v3/pkg/client/profile"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"
oidc_api "github.com/zitadel/zitadel/internal/api/oidc"
"github.com/zitadel/zitadel/internal/domain"
)
func TestServer_JWTProfile(t *testing.T) {
t.Parallel()
user, name, keyData, err := Instance.CreateOIDCJWTProfileClient(CTX)
require.NoError(t, err)
type claims struct {
name string
username string
updated time.Time
resourceOwnerID any
resourceOwnerName any
resourceOwnerPrimaryDomain any
orgDomain any
}
tests := []struct {
name string
keyData []byte
scope []string
wantClaims claims
wantErr bool
}{
{
name: "success",
keyData: keyData,
scope: []string{oidc.ScopeOpenID},
},
{
name: "openid, profile, email",
keyData: keyData,
scope: []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail},
wantClaims: claims{
name: name,
username: name,
updated: user.GetDetails().GetChangeDate().AsTime(),
},
},
{
name: "org id and domain scope",
keyData: keyData,
scope: []string{
oidc.ScopeOpenID,
domain.OrgIDScope + Instance.DefaultOrg.Id,
domain.OrgDomainPrimaryScope + Instance.DefaultOrg.PrimaryDomain,
},
wantClaims: claims{
resourceOwnerID: Instance.DefaultOrg.Id,
resourceOwnerName: Instance.DefaultOrg.Name,
resourceOwnerPrimaryDomain: Instance.DefaultOrg.PrimaryDomain,
orgDomain: Instance.DefaultOrg.PrimaryDomain,
},
},
{
name: "invalid org domain filtered",
keyData: keyData,
scope: []string{
oidc.ScopeOpenID,
domain.OrgDomainPrimaryScope + Instance.DefaultOrg.PrimaryDomain,
domain.OrgDomainPrimaryScope + "foo"},
wantClaims: claims{
orgDomain: Instance.DefaultOrg.PrimaryDomain,
},
},
{
name: "invalid org id filtered",
keyData: keyData,
scope: []string{oidc.ScopeOpenID,
domain.OrgIDScope + Instance.DefaultOrg.Id,
domain.OrgIDScope + "foo",
},
wantClaims: claims{
resourceOwnerID: Instance.DefaultOrg.Id,
resourceOwnerName: Instance.DefaultOrg.Name,
resourceOwnerPrimaryDomain: Instance.DefaultOrg.PrimaryDomain,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tokenSource, err := profile.NewJWTProfileTokenSourceFromKeyFileData(CTX, Instance.OIDCIssuer(), tt.keyData, tt.scope)
require.NoError(t, err)
var tokens *oauth2.Token
require.EventuallyWithT(
t, func(collect *assert.CollectT) {
tokens, err = tokenSource.TokenCtx(CTX)
if tt.wantErr {
assert.Error(collect, err)
return
}
assert.NoError(collect, err)
assert.NotNil(collect, tokens)
},
time.Minute, time.Second,
)
provider, err := rp.NewRelyingPartyOIDC(CTX, Instance.OIDCIssuer(), "", "", redirectURI, tt.scope)
require.NoError(t, err)
userinfo, err := rp.Userinfo[*oidc.UserInfo](CTX, tokens.AccessToken, oidc.BearerToken, user.GetUserId(), provider)
require.NoError(t, err)
assert.Equal(t, tt.wantClaims.resourceOwnerID, userinfo.Claims[oidc_api.ClaimResourceOwnerID])
assert.Equal(t, tt.wantClaims.resourceOwnerName, userinfo.Claims[oidc_api.ClaimResourceOwnerName])
assert.Equal(t, tt.wantClaims.resourceOwnerPrimaryDomain, userinfo.Claims[oidc_api.ClaimResourceOwnerPrimaryDomain])
assert.Equal(t, tt.wantClaims.orgDomain, userinfo.Claims[domain.OrgDomainPrimaryClaim])
assert.Equal(t, tt.wantClaims.name, userinfo.Name)
assert.Equal(t, tt.wantClaims.username, userinfo.PreferredUsername)
assertOIDCTime(t, userinfo.UpdatedAt, tt.wantClaims.updated)
assert.Empty(t, userinfo.UserInfoProfile.FamilyName)
assert.Empty(t, userinfo.UserInfoProfile.GivenName)
assert.Empty(t, userinfo.UserInfoEmail)
assert.Empty(t, userinfo.UserInfoPhone)
assert.Empty(t, userinfo.Address)
})
}
}