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:
Tim Möhlmann
2023-12-05 19:01:03 +02:00
committed by GitHub
parent 51cfb9564a
commit ec03340b67
46 changed files with 1666 additions and 781 deletions

View File

@@ -8,26 +8,30 @@ import (
"strings"
"time"
"github.com/brianvoe/gofakeit/v6"
"github.com/zitadel/oidc/v3/pkg/client"
"github.com/zitadel/oidc/v3/pkg/client/rp"
"github.com/zitadel/oidc/v3/pkg/client/rs"
"github.com/zitadel/oidc/v3/pkg/oidc"
"google.golang.org/protobuf/types/known/timestamppb"
http_util "github.com/zitadel/zitadel/internal/api/http"
oidc_internal "github.com/zitadel/zitadel/internal/api/oidc"
"github.com/zitadel/zitadel/pkg/grpc/app"
"github.com/zitadel/zitadel/pkg/grpc/authn"
"github.com/zitadel/zitadel/pkg/grpc/management"
"github.com/zitadel/zitadel/pkg/grpc/user"
)
func (s *Tester) CreateOIDCNativeClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) {
func (s *Tester) CreateOIDCClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string, appType app.OIDCAppType, authMethod app.OIDCAuthMethodType) (*management.AddOIDCAppResponse, error) {
return s.Client.Mgmt.AddOIDCApp(ctx, &management.AddOIDCAppRequest{
ProjectId: projectID,
Name: fmt.Sprintf("app-%d", time.Now().UnixNano()),
RedirectUris: []string{redirectURI},
ResponseTypes: []app.OIDCResponseType{app.OIDCResponseType_OIDC_RESPONSE_TYPE_CODE},
GrantTypes: []app.OIDCGrantType{app.OIDCGrantType_OIDC_GRANT_TYPE_AUTHORIZATION_CODE, app.OIDCGrantType_OIDC_GRANT_TYPE_REFRESH_TOKEN},
AppType: app.OIDCAppType_OIDC_APP_TYPE_NATIVE,
AuthMethodType: app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_NONE,
AppType: appType,
AuthMethodType: authMethod,
PostLogoutRedirectUris: []string{logoutRedirectURI},
Version: app.OIDCVersion_OIDC_VERSION_1_0,
DevMode: false,
@@ -41,6 +45,46 @@ func (s *Tester) CreateOIDCNativeClient(ctx context.Context, redirectURI, logout
})
}
func (s *Tester) CreateOIDCNativeClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) {
return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_NATIVE, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_NONE)
}
func (s *Tester) CreateOIDCWebClientBasic(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) {
return s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_BASIC)
}
func (s *Tester) CreateOIDCWebClientJWT(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (client *management.AddOIDCAppResponse, keyData []byte, err error) {
client, err = s.CreateOIDCClient(ctx, redirectURI, logoutRedirectURI, projectID, app.OIDCAppType_OIDC_APP_TYPE_WEB, app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_PRIVATE_KEY_JWT)
if err != nil {
return nil, nil, err
}
key, err := s.Client.Mgmt.AddAppKey(ctx, &management.AddAppKeyRequest{
ProjectId: projectID,
AppId: client.GetAppId(),
Type: authn.KeyType_KEY_TYPE_JSON,
ExpirationDate: timestamppb.New(time.Now().Add(time.Hour)),
})
if err != nil {
return nil, nil, err
}
return client, key.GetKeyDetails(), nil
}
func (s *Tester) CreateOIDCInactivateClient(ctx context.Context, redirectURI, logoutRedirectURI, projectID string) (*management.AddOIDCAppResponse, error) {
client, err := s.CreateOIDCNativeClient(ctx, redirectURI, logoutRedirectURI, projectID)
if err != nil {
return nil, err
}
_, err = s.Client.Mgmt.DeactivateApp(ctx, &management.DeactivateAppRequest{
ProjectId: projectID,
AppId: client.GetAppId(),
})
if err != nil {
return nil, err
}
return client, err
}
func (s *Tester) CreateOIDCImplicitFlowClient(ctx context.Context, redirectURI string) (*management.AddOIDCAppResponse, error) {
project, err := s.Client.Mgmt.AddProject(ctx, &management.AddProjectRequest{
Name: fmt.Sprintf("project-%d", time.Now().UnixNano()),
@@ -83,14 +127,14 @@ func (s *Tester) CreateAPIClient(ctx context.Context, projectID string) (*manage
})
}
const CodeVerifier = "codeVerifier"
func (s *Tester) CreateOIDCAuthRequest(ctx context.Context, clientID, loginClient, redirectURI string, scope ...string) (authRequestID string, err error) {
provider, err := s.CreateRelyingParty(ctx, clientID, redirectURI, scope...)
if err != nil {
return "", err
}
codeVerifier := "codeVerifier"
codeChallenge := oidc.NewSHACodeChallenge(codeVerifier)
codeChallenge := oidc.NewSHACodeChallenge(CodeVerifier)
authURL := rp.AuthURL("state", provider, rp.WithCodeChallenge(codeChallenge))
req, err := GetRequest(authURL, map[string]string{oidc_internal.LoginClientHeader: loginClient})
@@ -196,3 +240,22 @@ func CheckRedirect(req *http.Request) (*url.URL, error) {
return resp.Location()
}
func (s *Tester) CreateOIDCCredentialsClient(ctx context.Context) (string, string, error) {
name := gofakeit.Username()
user, err := s.Client.Mgmt.AddMachineUser(ctx, &management.AddMachineUserRequest{
Name: name,
UserName: name,
AccessTokenType: user.AccessTokenType_ACCESS_TOKEN_TYPE_JWT,
})
if err != nil {
return "", "", err
}
secret, err := s.Client.Mgmt.GenerateMachineSecret(ctx, &management.GenerateMachineSecretRequest{
UserId: user.GetUserId(),
})
if err != nil {
return "", "", err
}
return secret.GetClientId(), secret.GetClientSecret(), nil
}