mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 00:17:32 +00:00
perf(oidc): optimize client verification (#6999)
* fix some spelling errors
* client credential auth
* implementation of client auth
* improve error handling
* unit test command package
* unit test database package
* unit test query package
* cleanup unused tracing func
* fix integration tests
* errz to zerrors
* fix linting and import issues
* fix another linting error
* integration test with client secret
* Revert "integration test with client secret"
This reverts commit 0814ba522f
.
* add integration tests
* client credentials integration test
* resolve comments
* pin oidc v3.5.0
This commit is contained in:
167
internal/query/oidc_client_test.go
Normal file
167
internal/query/oidc_client_test.go
Normal file
@@ -0,0 +1,167 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
_ "embed"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/database"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
zerrors "github.com/zitadel/zitadel/internal/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed testdata/oidc_client_jwt.json
|
||||
testdataOidcClientJWT string
|
||||
//go:embed testdata/oidc_client_public.json
|
||||
testdataOidcClientPublic string
|
||||
//go:embed testdata/oidc_client_secret.json
|
||||
testdataOidcClientSecret string
|
||||
)
|
||||
|
||||
func TestQueries_GetOIDCClientByID(t *testing.T) {
|
||||
expQuery := regexp.QuoteMeta(oidcClientQuery)
|
||||
cols := []string{"client"}
|
||||
pubkey := `-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2ufAL1b72bIy1ar+Ws6b
|
||||
GohJJQFB7dfRapDqeqM8Ukp6CVdPzq/pOz1viAq50yzWZJryF+2wshFAKGF9A2/B
|
||||
2Yf9bJXPZ/KbkFrYT3NTvYDkvlaSTl9mMnzrU29s48F1PTWKfB+C3aMsOEG1BufV
|
||||
s63qF4nrEPjSbhljIco9FZq4XppIzhMQ0fDdA/+XygCJqvuaL0LibM1KrlUdnu71
|
||||
YekhSJjEPnvOisXIk4IXywoGIOwtjxkDvNItQvaMVldr4/kb6uvbgdWwq5EwBZXq
|
||||
low2kyJov38V4Uk2I8kuXpLcnrpw5Tio2ooiUE27b0vHZqBKOei9Uo88qCrn3EKx
|
||||
6QIDAQAB
|
||||
-----END RSA PUBLIC KEY-----
|
||||
`
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
mock sqlExpectation
|
||||
want *OIDCClient
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "no rows",
|
||||
mock: mockQueryErr(expQuery, sql.ErrNoRows, "instanceID", "clientID", true),
|
||||
wantErr: zerrors.ThrowNotFound(sql.ErrNoRows, "QUERY-wu6Ee", "Errors.App.NotFound"),
|
||||
},
|
||||
{
|
||||
name: "internal error",
|
||||
mock: mockQueryErr(expQuery, sql.ErrConnDone, "instanceID", "clientID", true),
|
||||
wantErr: zerrors.ThrowInternal(sql.ErrConnDone, "QUERY-ieR7R", "Errors.Internal"),
|
||||
},
|
||||
{
|
||||
name: "jwt client",
|
||||
mock: mockQuery(expQuery, cols, []driver.Value{testdataOidcClientJWT}, "instanceID", "clientID", true),
|
||||
want: &OIDCClient{
|
||||
InstanceID: "230690539048009730",
|
||||
AppID: "236647088211886082",
|
||||
State: domain.AppStateActive,
|
||||
ClientID: "236647088211951618@tests",
|
||||
ClientSecret: nil,
|
||||
RedirectURIs: []string{"http://localhost:9999/auth/callback"},
|
||||
ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeCode},
|
||||
GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode, domain.OIDCGrantTypeRefreshToken},
|
||||
ApplicationType: domain.OIDCApplicationTypeWeb,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypePrivateKeyJWT,
|
||||
PostLogoutRedirectURIs: []string{"https://example.com/logout"},
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeJWT,
|
||||
AccessTokenRoleAssertion: true,
|
||||
IDTokenRoleAssertion: true,
|
||||
IDTokenUserinfoAssertion: true,
|
||||
ClockSkew: 1000000000,
|
||||
AdditionalOrigins: []string{"https://example.com"},
|
||||
ProjectID: "236645808328409090",
|
||||
PublicKeys: map[string][]byte{"236647201860747266": []byte(pubkey)},
|
||||
ProjectRoleKeys: []string{"role1", "role2"},
|
||||
AccessTokenLifetime: 43200000000000,
|
||||
IDTokenLifetime: 43200000000000,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "public client",
|
||||
mock: mockQuery(expQuery, cols, []driver.Value{testdataOidcClientPublic}, "instanceID", "clientID", true),
|
||||
want: &OIDCClient{
|
||||
InstanceID: "230690539048009730",
|
||||
AppID: "236646457053020162",
|
||||
State: domain.AppStateActive,
|
||||
ClientID: "236646457053085698@tests",
|
||||
ClientSecret: nil,
|
||||
RedirectURIs: []string{"http://localhost:9999/auth/callback"},
|
||||
ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeCode},
|
||||
GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
|
||||
ApplicationType: domain.OIDCApplicationTypeWeb,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeNone,
|
||||
PostLogoutRedirectURIs: nil,
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeBearer,
|
||||
AccessTokenRoleAssertion: false,
|
||||
IDTokenRoleAssertion: false,
|
||||
IDTokenUserinfoAssertion: false,
|
||||
ClockSkew: 0,
|
||||
AdditionalOrigins: nil,
|
||||
PublicKeys: nil,
|
||||
ProjectID: "236645808328409090",
|
||||
ProjectRoleKeys: []string{"role1", "role2"},
|
||||
AccessTokenLifetime: 43200000000000,
|
||||
IDTokenLifetime: 43200000000000,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "secret client",
|
||||
mock: mockQuery(expQuery, cols, []driver.Value{testdataOidcClientSecret}, "instanceID", "clientID", true),
|
||||
want: &OIDCClient{
|
||||
InstanceID: "230690539048009730",
|
||||
AppID: "236646858984783874",
|
||||
State: domain.AppStateActive,
|
||||
ClientID: "236646858984849410@tests",
|
||||
ClientSecret: &crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeHash,
|
||||
Algorithm: "bcrypt",
|
||||
Crypted: []byte(`$2a$14$OzZ0XEZZEtD13py/EPba2evsS6WcKZ5orVMj9pWHEGEHmLu2h3PFq`),
|
||||
},
|
||||
RedirectURIs: []string{"http://localhost:9999/auth/callback"},
|
||||
ResponseTypes: []domain.OIDCResponseType{0},
|
||||
GrantTypes: []domain.OIDCGrantType{0},
|
||||
ApplicationType: domain.OIDCApplicationTypeWeb,
|
||||
AuthMethodType: domain.OIDCAuthMethodTypeBasic,
|
||||
PostLogoutRedirectURIs: nil,
|
||||
IsDevMode: true,
|
||||
AccessTokenType: domain.OIDCTokenTypeBearer,
|
||||
AccessTokenRoleAssertion: false,
|
||||
IDTokenRoleAssertion: false,
|
||||
IDTokenUserinfoAssertion: false,
|
||||
ClockSkew: 0,
|
||||
AdditionalOrigins: nil,
|
||||
PublicKeys: nil,
|
||||
ProjectID: "236645808328409090",
|
||||
ProjectRoleKeys: []string{"role1", "role2"},
|
||||
AccessTokenLifetime: 43200000000000,
|
||||
IDTokenLifetime: 43200000000000,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
execMock(t, tt.mock, func(db *sql.DB) {
|
||||
q := &Queries{
|
||||
client: &database.DB{
|
||||
DB: db,
|
||||
Database: &prepareDB{},
|
||||
},
|
||||
}
|
||||
ctx := authz.NewMockContext("instanceID", "orgID", "loginClient")
|
||||
got, err := q.GetOIDCClientByID(ctx, "clientID", true)
|
||||
require.ErrorIs(t, err, tt.wantErr)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user