feat(crypto): use passwap for machine and app secrets (#7657)

* feat(crypto): use passwap for machine and app secrets

* fix command package tests

* add hash generator command test

* naming convention, fix query tests

* rename PasswordHasher and cleanup start commands

* add reducer tests

* fix intergration tests, cleanup old config

* add app secret unit tests

* solve setup panics

* fix push of updated events

* add missing event translations

* update documentation

* solve linter errors

* remove nolint:SA1019 as it doesn't seem to help anyway

* add nolint to deprecated filter usage

* update users migration version

* remove unused ClientSecret from APIConfigChangedEvent

---------

Co-authored-by: Livio Spring <[email protected]>
This commit is contained in:
Tim Möhlmann
2024-04-05 09:35:49 +00:00
committed by GitHub
co-authored by Livio Spring
parent 5931fb8f28
commit 2089992d75
135 changed files with 2407 additions and 1779 deletions
+32 -23
View File
@@ -6,6 +6,7 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"net/http"
"strconv"
@@ -33,9 +34,10 @@ type Commands struct {
jobs sync.WaitGroup
checkPermission domain.PermissionCheck
newCode cryptoCodeFunc
newCodeWithDefault cryptoCodeWithDefaultFunc
checkPermission domain.PermissionCheck
newEncryptedCode encrypedCodeFunc
newEncryptedCodeWithDefault encryptedCodeWithDefaultFunc
newHashedSecret hashedSecretFunc
eventstore *eventstore.Eventstore
static static.Storage
@@ -49,8 +51,8 @@ type Commands struct {
smtpEncryption crypto.EncryptionAlgorithm
smsEncryption crypto.EncryptionAlgorithm
userEncryption crypto.EncryptionAlgorithm
userPasswordHasher *crypto.PasswordHasher
codeAlg crypto.HashAlgorithm
userPasswordHasher *crypto.Hasher
secretHasher *crypto.Hasher
machineKeySize int
applicationKeySize int
domainVerificationAlg crypto.EncryptionAlgorithm
@@ -106,6 +108,15 @@ func StartCommands(
idGenerator := id.SonyFlakeGenerator()
// reuse the oidcEncryption to be able to handle both tokens in the interceptor later on
sessionAlg := oidcEncryption
secretHasher, err := defaults.SecretHasher.NewHasher()
if err != nil {
return nil, fmt.Errorf("secret hasher: %w", err)
}
userPasswordHasher, err := defaults.PasswordHasher.NewHasher()
if err != nil {
return nil, fmt.Errorf("password hasher: %w", err)
}
repo = &Commands{
eventstore: es,
static: staticStore,
@@ -123,14 +134,20 @@ func StartCommands(
smtpEncryption: smtpEncryption,
smsEncryption: smsEncryption,
userEncryption: userEncryption,
userPasswordHasher: userPasswordHasher,
secretHasher: secretHasher,
machineKeySize: int(defaults.SecretGenerators.MachineKeySize),
applicationKeySize: int(defaults.SecretGenerators.ApplicationKeySize),
domainVerificationAlg: domainVerificationEncryption,
domainVerificationGenerator: crypto.NewEncryptionGenerator(defaults.DomainVerification.VerificationGenerator, domainVerificationEncryption),
domainVerificationValidator: api_http.ValidateDomain,
keyAlgorithm: oidcEncryption,
certificateAlgorithm: samlEncryption,
webauthnConfig: webAuthN,
httpClient: httpClient,
checkPermission: permissionCheck,
newCode: newCryptoCode,
newCodeWithDefault: newCryptoCodeWithDefaultConfig,
newEncryptedCode: newEncryptedCode,
newEncryptedCodeWithDefault: newEncryptedCodeWithDefaultConfig,
sessionTokenCreator: sessionTokenCreator(idGenerator, sessionAlg),
sessionTokenVerifier: sessionTokenVerifier,
defaultAccessTokenLifetime: defaultAccessTokenLifetime,
@@ -145,25 +162,17 @@ func StartCommands(
GrpcServiceExisting: func(service string) bool { return false },
GrpcMethodExisting: func(method string) bool { return false },
ActionFunctionExisting: domain.FunctionExists(),
}
repo.codeAlg = crypto.NewBCrypt(defaults.SecretGenerators.PasswordSaltCost)
repo.userPasswordHasher, err = defaults.PasswordHasher.PasswordHasher()
if err != nil {
return nil, err
}
repo.machineKeySize = int(defaults.SecretGenerators.MachineKeySize)
repo.applicationKeySize = int(defaults.SecretGenerators.ApplicationKeySize)
repo.multifactors = domain.MultifactorConfigs{
OTP: domain.OTPConfig{
CryptoMFA: otpEncryption,
Issuer: defaults.Multifactors.OTP.Issuer,
multifactors: domain.MultifactorConfigs{
OTP: domain.OTPConfig{
CryptoMFA: otpEncryption,
Issuer: defaults.Multifactors.OTP.Issuer,
},
},
}
repo.domainVerificationGenerator = crypto.NewEncryptionGenerator(defaults.DomainVerification.VerificationGenerator, repo.domainVerificationAlg)
repo.domainVerificationValidator = api_http.ValidateDomain
if defaultSecretGenerators != nil && defaultSecretGenerators.ClientSecret != nil {
repo.newHashedSecret = newHashedSecretWithDefault(secretHasher, defaultSecretGenerators.ClientSecret)
}
return repo, nil
}
+29 -24
View File
@@ -7,27 +7,26 @@ import (
"github.com/zitadel/zitadel/internal/command/preparation"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/zerrors"
)
type cryptoCodeFunc func(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.Crypto) (*CryptoCode, error)
type encrypedCodeFunc func(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.EncryptionAlgorithm) (*EncryptedCode, error)
type cryptoCodeWithDefaultFunc func(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.Crypto, defaultConfig *crypto.GeneratorConfig) (*CryptoCode, error)
type encryptedCodeWithDefaultFunc func(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.EncryptionAlgorithm, defaultConfig *crypto.GeneratorConfig) (*EncryptedCode, error)
var emptyConfig = &crypto.GeneratorConfig{}
type CryptoCode struct {
type EncryptedCode struct {
Crypted *crypto.CryptoValue
Plain string
Expiry time.Duration
}
func newCryptoCode(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.Crypto) (*CryptoCode, error) {
return newCryptoCodeWithDefaultConfig(ctx, filter, typ, alg, emptyConfig)
func newEncryptedCode(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.EncryptionAlgorithm) (*EncryptedCode, error) {
return newEncryptedCodeWithDefaultConfig(ctx, filter, typ, alg, emptyConfig)
}
func newCryptoCodeWithDefaultConfig(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.Crypto, defaultConfig *crypto.GeneratorConfig) (*CryptoCode, error) {
gen, config, err := secretGenerator(ctx, filter, typ, alg, defaultConfig)
func newEncryptedCodeWithDefaultConfig(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.EncryptionAlgorithm, defaultConfig *crypto.GeneratorConfig) (*EncryptedCode, error) {
gen, config, err := encryptedCodeGenerator(ctx, filter, typ, alg, defaultConfig)
if err != nil {
return nil, err
}
@@ -35,41 +34,47 @@ func newCryptoCodeWithDefaultConfig(ctx context.Context, filter preparation.Filt
if err != nil {
return nil, err
}
return &CryptoCode{
return &EncryptedCode{
Crypted: crypted,
Plain: plain,
Expiry: config.Expiry,
}, nil
}
func verifyCryptoCode(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.Crypto, creation time.Time, expiry time.Duration, crypted *crypto.CryptoValue, plain string) error {
gen, _, err := secretGenerator(ctx, filter, typ, alg, emptyConfig)
func verifyEncryptedCode(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.EncryptionAlgorithm, creation time.Time, expiry time.Duration, crypted *crypto.CryptoValue, plain string) error {
gen, _, err := encryptedCodeGenerator(ctx, filter, typ, alg, emptyConfig)
if err != nil {
return err
}
return crypto.VerifyCode(creation, expiry, crypted, plain, gen)
return crypto.VerifyCode(creation, expiry, crypted, plain, gen.Alg())
}
func secretGenerator(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.Crypto, defaultConfig *crypto.GeneratorConfig) (crypto.Generator, *crypto.GeneratorConfig, error) {
config, err := secretGeneratorConfigWithDefault(ctx, filter, typ, defaultConfig)
func encryptedCodeGenerator(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, alg crypto.EncryptionAlgorithm, defaultConfig *crypto.GeneratorConfig) (crypto.Generator, *crypto.GeneratorConfig, error) {
config, err := cryptoGeneratorConfigWithDefault(ctx, filter, typ, defaultConfig)
if err != nil {
return nil, nil, err
}
switch a := alg.(type) {
case crypto.HashAlgorithm:
return crypto.NewHashGenerator(*config, a), config, nil
case crypto.EncryptionAlgorithm:
return crypto.NewEncryptionGenerator(*config, a), config, nil
default:
return nil, nil, zerrors.ThrowInternalf(nil, "COMMA-RreV6", "Errors.Internal unsupported crypto algorithm type %T", a)
return crypto.NewEncryptionGenerator(*config, alg), config, nil
}
type hashedSecretFunc func(ctx context.Context, filter preparation.FilterToQueryReducer) (encodedHash, plain string, err error)
func newHashedSecretWithDefault(hasher *crypto.Hasher, defaultConfig *crypto.GeneratorConfig) hashedSecretFunc {
return func(ctx context.Context, filter preparation.FilterToQueryReducer) (encodedHash string, plain string, err error) {
config, err := cryptoGeneratorConfigWithDefault(ctx, filter, domain.SecretGeneratorTypeAppSecret, defaultConfig)
if err != nil {
return "", "", err
}
generator := crypto.NewHashGenerator(*config, hasher)
return generator.NewCode()
}
}
func secretGeneratorConfig(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType) (*crypto.GeneratorConfig, error) {
return secretGeneratorConfigWithDefault(ctx, filter, typ, emptyConfig)
func cryptoGeneratorConfig(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType) (*crypto.GeneratorConfig, error) {
return cryptoGeneratorConfigWithDefault(ctx, filter, typ, emptyConfig)
}
func secretGeneratorConfigWithDefault(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, defaultConfig *crypto.GeneratorConfig) (*crypto.GeneratorConfig, error) {
func cryptoGeneratorConfigWithDefault(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, defaultConfig *crypto.GeneratorConfig) (*crypto.GeneratorConfig, error) {
wm := NewInstanceSecretGeneratorConfigWriteModel(ctx, typ)
events, err := filter(ctx, wm.Query())
if err != nil {
+94 -57
View File
@@ -8,6 +8,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/passwap"
"github.com/zitadel/passwap/bcrypt"
"go.uber.org/mock/gomock"
"github.com/zitadel/zitadel/internal/command/preparation"
@@ -15,12 +17,11 @@ import (
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/instance"
"github.com/zitadel/zitadel/internal/zerrors"
)
func mockCode(code string, exp time.Duration) cryptoCodeFunc {
return func(ctx context.Context, filter preparation.FilterToQueryReducer, _ domain.SecretGeneratorType, alg crypto.Crypto) (*CryptoCode, error) {
return &CryptoCode{
func mockEncryptedCode(code string, exp time.Duration) encrypedCodeFunc {
return func(ctx context.Context, filter preparation.FilterToQueryReducer, _ domain.SecretGeneratorType, alg crypto.EncryptionAlgorithm) (*EncryptedCode, error) {
return &EncryptedCode{
Crypted: &crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@@ -33,9 +34,9 @@ func mockCode(code string, exp time.Duration) cryptoCodeFunc {
}
}
func mockCodeWithDefault(code string, exp time.Duration) cryptoCodeWithDefaultFunc {
return func(ctx context.Context, filter preparation.FilterToQueryReducer, _ domain.SecretGeneratorType, alg crypto.Crypto, _ *crypto.GeneratorConfig) (*CryptoCode, error) {
return &CryptoCode{
func mockEncryptedCodeWithDefault(code string, exp time.Duration) encryptedCodeWithDefaultFunc {
return func(ctx context.Context, filter preparation.FilterToQueryReducer, _ domain.SecretGeneratorType, alg crypto.EncryptionAlgorithm, _ *crypto.GeneratorConfig) (*EncryptedCode, error) {
return &EncryptedCode{
Crypted: &crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
@@ -48,6 +49,12 @@ func mockCodeWithDefault(code string, exp time.Duration) cryptoCodeWithDefaultFu
}
}
func mockHashedSecret(secret string) hashedSecretFunc {
return func(_ context.Context, _ preparation.FilterToQueryReducer) (encodedHash string, plain string, err error) {
return secret, secret, nil
}
}
var (
testGeneratorConfig = crypto.GeneratorConfig{
Length: 12,
@@ -74,7 +81,7 @@ func testSecretGeneratorAddedEvent(typ domain.SecretGeneratorType) *instance.Sec
func Test_newCryptoCode(t *testing.T) {
type args struct {
typ domain.SecretGeneratorType
alg crypto.Crypto
alg crypto.EncryptionAlgorithm
}
tests := []struct {
name string
@@ -87,7 +94,7 @@ func Test_newCryptoCode(t *testing.T) {
eventstore: eventstoreExpect(t, expectFilterError(io.ErrClosedPipe)),
args: args{
typ: domain.SecretGeneratorTypeVerifyEmailCode,
alg: crypto.CreateMockHashAlg(gomock.NewController(t)),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
wantErr: io.ErrClosedPipe,
},
@@ -98,13 +105,13 @@ func Test_newCryptoCode(t *testing.T) {
)),
args: args{
typ: domain.SecretGeneratorTypeVerifyEmailCode,
alg: crypto.CreateMockHashAlg(gomock.NewController(t)),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := newCryptoCode(context.Background(), tt.eventstore.Filter, tt.args.typ, tt.args.alg)
got, err := newEncryptedCode(context.Background(), tt.eventstore.Filter, tt.args.typ, tt.args.alg) //nolint:staticcheck
require.ErrorIs(t, err, tt.wantErr)
if tt.wantErr == nil {
require.NotNil(t, got)
@@ -120,12 +127,12 @@ func Test_verifyCryptoCode(t *testing.T) {
es := eventstoreExpect(t, expectFilter(
eventFromEventPusher(testSecretGeneratorAddedEvent(domain.SecretGeneratorTypeVerifyEmailCode)),
))
code, err := newCryptoCode(context.Background(), es.Filter, domain.SecretGeneratorTypeVerifyEmailCode, crypto.CreateMockHashAlg(gomock.NewController(t)))
code, err := newEncryptedCode(context.Background(), es.Filter, domain.SecretGeneratorTypeVerifyEmailCode, crypto.CreateMockEncryptionAlg(gomock.NewController(t))) //nolint:staticcheck
require.NoError(t, err)
type args struct {
typ domain.SecretGeneratorType
alg crypto.Crypto
alg crypto.EncryptionAlgorithm
expiry time.Duration
crypted *crypto.CryptoValue
plain string
@@ -141,7 +148,7 @@ func Test_verifyCryptoCode(t *testing.T) {
eventsore: eventstoreExpect(t, expectFilterError(io.ErrClosedPipe)),
args: args{
typ: domain.SecretGeneratorTypeVerifyEmailCode,
alg: crypto.CreateMockHashAlg(gomock.NewController(t)),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
expiry: code.Expiry,
crypted: code.Crypted,
plain: code.Plain,
@@ -155,7 +162,7 @@ func Test_verifyCryptoCode(t *testing.T) {
)),
args: args{
typ: domain.SecretGeneratorTypeVerifyEmailCode,
alg: crypto.CreateMockHashAlg(gomock.NewController(t)),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
expiry: code.Expiry,
crypted: code.Crypted,
plain: code.Plain,
@@ -168,7 +175,7 @@ func Test_verifyCryptoCode(t *testing.T) {
)),
args: args{
typ: domain.SecretGeneratorTypeVerifyEmailCode,
alg: crypto.CreateMockHashAlg(gomock.NewController(t)),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
expiry: code.Expiry,
crypted: code.Crypted,
plain: "wrong",
@@ -178,7 +185,7 @@ func Test_verifyCryptoCode(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := verifyCryptoCode(context.Background(), tt.eventsore.Filter, tt.args.typ, tt.args.alg, time.Now(), tt.args.expiry, tt.args.crypted, tt.args.plain)
err := verifyEncryptedCode(context.Background(), tt.eventsore.Filter, tt.args.typ, tt.args.alg, time.Now(), tt.args.expiry, tt.args.crypted, tt.args.plain) //nolint:staticcheck
if tt.wantErr {
assert.Error(t, err)
return
@@ -188,10 +195,10 @@ func Test_verifyCryptoCode(t *testing.T) {
}
}
func Test_secretGenerator(t *testing.T) {
func Test_cryptoCodeGenerator(t *testing.T) {
type args struct {
typ domain.SecretGeneratorType
alg crypto.Crypto
alg crypto.EncryptionAlgorithm
defaultConfig *crypto.GeneratorConfig
}
tests := []struct {
@@ -207,24 +214,11 @@ func Test_secretGenerator(t *testing.T) {
eventsore: eventstoreExpect(t, expectFilterError(io.ErrClosedPipe)),
args: args{
typ: domain.SecretGeneratorTypeVerifyEmailCode,
alg: crypto.CreateMockHashAlg(gomock.NewController(t)),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
defaultConfig: emptyConfig,
},
wantErr: io.ErrClosedPipe,
},
{
name: "hash generator",
eventsore: eventstoreExpect(t, expectFilter(
eventFromEventPusher(testSecretGeneratorAddedEvent(domain.SecretGeneratorTypeVerifyEmailCode)),
)),
args: args{
typ: domain.SecretGeneratorTypeVerifyEmailCode,
alg: crypto.CreateMockHashAlg(gomock.NewController(t)),
defaultConfig: emptyConfig,
},
want: crypto.NewHashGenerator(testGeneratorConfig, crypto.CreateMockHashAlg(gomock.NewController(t))),
wantConf: &testGeneratorConfig,
},
{
name: "encryption generator",
eventsore: eventstoreExpect(t, expectFilter(
@@ -238,17 +232,6 @@ func Test_secretGenerator(t *testing.T) {
want: crypto.NewEncryptionGenerator(testGeneratorConfig, crypto.CreateMockEncryptionAlg(gomock.NewController(t))),
wantConf: &testGeneratorConfig,
},
{
name: "hash generator with default config",
eventsore: eventstoreExpect(t, expectFilter()),
args: args{
typ: domain.SecretGeneratorTypeVerifyEmailCode,
alg: crypto.CreateMockHashAlg(gomock.NewController(t)),
defaultConfig: &testGeneratorConfig,
},
want: crypto.NewHashGenerator(testGeneratorConfig, crypto.CreateMockHashAlg(gomock.NewController(t))),
wantConf: &testGeneratorConfig,
},
{
name: "encryption generator with default config",
eventsore: eventstoreExpect(t, expectFilter()),
@@ -260,25 +243,79 @@ func Test_secretGenerator(t *testing.T) {
want: crypto.NewEncryptionGenerator(testGeneratorConfig, crypto.CreateMockEncryptionAlg(gomock.NewController(t))),
wantConf: &testGeneratorConfig,
},
{
name: "unsupported type",
eventsore: eventstoreExpect(t, expectFilter(
eventFromEventPusher(testSecretGeneratorAddedEvent(domain.SecretGeneratorTypeVerifyEmailCode)),
)),
args: args{
typ: domain.SecretGeneratorTypeVerifyEmailCode,
alg: nil,
defaultConfig: emptyConfig,
},
wantErr: zerrors.ThrowInternalf(nil, "COMMA-RreV6", "Errors.Internal unsupported crypto algorithm type %T", nil),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, gotConf, err := secretGenerator(context.Background(), tt.eventsore.Filter, tt.args.typ, tt.args.alg, tt.args.defaultConfig)
got, gotConf, err := encryptedCodeGenerator(context.Background(), tt.eventsore.Filter, tt.args.typ, tt.args.alg, tt.args.defaultConfig) //nolint:staticcheck
require.ErrorIs(t, err, tt.wantErr)
assert.IsType(t, tt.want, got)
assert.Equal(t, tt.wantConf, gotConf)
})
}
}
func Test_newHashedSecretWithDefault(t *testing.T) {
tests := []struct {
name string
eventstore func(*testing.T) *eventstore.Eventstore
wantLen int
wantErr bool
}{
{
name: "filter error",
eventstore: expectEventstore(
expectFilterError(io.ErrClosedPipe),
),
wantErr: true,
},
{
name: "default config",
eventstore: expectEventstore(
expectFilter(),
),
wantLen: 32,
},
{
name: "instance config",
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
instance.NewSecretGeneratorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecretGeneratorTypeAppSecret,
24,
time.Hour*1,
true,
true,
true,
true,
),
),
),
),
wantLen: 24,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
hasher := &crypto.Hasher{
Swapper: passwap.NewSwapper(bcrypt.New(bcrypt.MinCost)),
}
defaultConfig := &crypto.GeneratorConfig{
Length: 32,
Expiry: time.Minute,
IncludeLowerLetters: true,
}
generate := newHashedSecretWithDefault(hasher, defaultConfig)
encodedHash, plain, err := generate(context.Background(), tt.eventstore(t).Filter) //nolint:staticcheck
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Len(t, plain, tt.wantLen)
_, err = hasher.Verify(encodedHash, plain)
require.NoError(t, err)
})
}
}
+2 -2
View File
@@ -23,6 +23,6 @@ func (e *Email) Validate() error {
return e.Address.Validate()
}
func (c *Commands) newEmailCode(ctx context.Context, filter preparation.FilterToQueryReducer, alg crypto.EncryptionAlgorithm) (*CryptoCode, error) {
return c.newCode(ctx, filter, domain.SecretGeneratorTypeVerifyEmailCode, alg)
func (c *Commands) newEmailCode(ctx context.Context, filter preparation.FilterToQueryReducer, alg crypto.EncryptionAlgorithm) (*EncryptedCode, error) {
return c.newEncryptedCode(ctx, filter, domain.SecretGeneratorTypeVerifyEmailCode, alg)
}
+11 -11
View File
@@ -108,7 +108,7 @@ func (wm *OAuthIDPWriteModel) NewChanges(
name,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
authorizationEndpoint,
tokenEndpoint,
userEndpoint,
@@ -278,7 +278,7 @@ func (wm *OIDCIDPWriteModel) NewChanges(
issuer,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
idTokenMapping bool,
options idp.Options,
@@ -636,7 +636,7 @@ func (wm *AzureADIDPWriteModel) NewChanges(
name string,
clientID string,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
tenant string,
isEmailVerified bool,
@@ -772,7 +772,7 @@ func (wm *GitHubIDPWriteModel) NewChanges(
name,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) ([]idp.GitHubIDPChanges, error) {
@@ -904,7 +904,7 @@ func (wm *GitHubEnterpriseIDPWriteModel) NewChanges(
name,
clientID string,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
authorizationEndpoint,
tokenEndpoint,
userEndpoint string,
@@ -1037,7 +1037,7 @@ func (wm *GitLabIDPWriteModel) NewChanges(
name,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) ([]idp.GitLabIDPChanges, error) {
@@ -1161,7 +1161,7 @@ func (wm *GitLabSelfHostedIDPWriteModel) NewChanges(
issuer string,
clientID string,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) ([]idp.GitLabSelfHostedIDPChanges, error) {
@@ -1285,7 +1285,7 @@ func (wm *GoogleIDPWriteModel) NewChanges(
name string,
clientID string,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) ([]idp.GoogleIDPChanges, error) {
@@ -1460,7 +1460,7 @@ func (wm *LDAPIDPWriteModel) NewChanges(
userObjectClasses []string,
userFilters []string,
timeout time.Duration,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
attributes idp.LDAPAttributes,
options idp.Options,
) ([]idp.LDAPIDPChanges, error) {
@@ -1653,7 +1653,7 @@ func (wm *AppleIDPWriteModel) NewChanges(
teamID string,
keyID string,
privateKey []byte,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) ([]idp.AppleIDPChanges, error) {
@@ -1790,7 +1790,7 @@ func (wm *SAMLIDPWriteModel) NewChanges(
metadata,
key,
certificate []byte,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
binding string,
withSignedRequest bool,
options idp.Options,
+1 -5
View File
@@ -126,7 +126,6 @@ type SetQuotas struct {
}
type SecretGenerators struct {
PasswordSaltCost uint
ClientSecret *crypto.GeneratorConfig
InitializeUserCode *crypto.GeneratorConfig
EmailVerificationCode *crypto.GeneratorConfig
@@ -457,7 +456,6 @@ func setupMinimalInterfaces(commands *Commands, validations *[]preparation.Valid
},
AuthMethodType: domain.APIAuthMethodTypePrivateKeyJWT,
},
nil,
),
commands.AddAPIAppCommand(
@@ -469,7 +467,6 @@ func setupMinimalInterfaces(commands *Commands, validations *[]preparation.Valid
},
AuthMethodType: domain.APIAuthMethodTypePrivateKeyJWT,
},
nil,
),
commands.AddAPIAppCommand(
@@ -481,10 +478,9 @@ func setupMinimalInterfaces(commands *Commands, validations *[]preparation.Valid
},
AuthMethodType: domain.APIAuthMethodTypePrivateKeyJWT,
},
nil,
),
commands.AddOIDCAppCommand(cnsl, nil),
commands.AddOIDCAppCommand(cnsl),
SetIAMConsoleID(instanceAgg, &cnsl.ClientID, &ids.consoleAppID),
)
}
+1 -7
View File
@@ -8,7 +8,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/instance"
@@ -141,12 +140,7 @@ func TestCommandSide_AddInstanceDomain(t *testing.T) {
domain.OIDCVersionV1,
"consoleApplicationID",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
[]string{"https://test.ch"},
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
+11 -11
View File
@@ -61,7 +61,7 @@ func (wm *InstanceOAuthIDPWriteModel) NewChangedEvent(
name,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
authorizationEndpoint,
tokenEndpoint,
userEndpoint,
@@ -171,7 +171,7 @@ func (wm *InstanceOIDCIDPWriteModel) NewChangedEvent(
issuer,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
idTokenMapping bool,
options idp.Options,
@@ -344,7 +344,7 @@ func (wm *InstanceAzureADIDPWriteModel) NewChangedEvent(
name,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
tenant string,
isEmailVerified bool,
@@ -420,7 +420,7 @@ func (wm *InstanceGitHubIDPWriteModel) NewChangedEvent(
name,
clientID string,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) (*instance.GitHubIDPChangedEvent, error) {
@@ -485,7 +485,7 @@ func (wm *InstanceGitHubEnterpriseIDPWriteModel) NewChangedEvent(
name,
clientID string,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
authorizationEndpoint,
tokenEndpoint,
userEndpoint string,
@@ -563,7 +563,7 @@ func (wm *InstanceGitLabIDPWriteModel) NewChangedEvent(
name,
clientID string,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) (*instance.GitLabIDPChangedEvent, error) {
@@ -629,7 +629,7 @@ func (wm *InstanceGitLabSelfHostedIDPWriteModel) NewChangedEvent(
issuer,
clientID string,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) (*instance.GitLabSelfHostedIDPChangedEvent, error) {
@@ -695,7 +695,7 @@ func (wm *InstanceGoogleIDPWriteModel) NewChangedEvent(
name,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) (*instance.GoogleIDPChangedEvent, error) {
@@ -767,7 +767,7 @@ func (wm *InstanceLDAPIDPWriteModel) NewChangedEvent(
userObjectClasses []string,
userFilters []string,
timeout time.Duration,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
attributes idp.LDAPAttributes,
options idp.Options,
) (*instance.LDAPIDPChangedEvent, error) {
@@ -848,7 +848,7 @@ func (wm *InstanceAppleIDPWriteModel) NewChangedEvent(
teamID,
keyID string,
privateKey []byte,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) (*instance.AppleIDPChangedEvent, error) {
@@ -912,7 +912,7 @@ func (wm *InstanceSAMLIDPWriteModel) NewChangedEvent(
metadata,
key,
certificate []byte,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
binding string,
withSignedRequest bool,
options idp.Options,
@@ -93,7 +93,7 @@ func (wm *InstanceIDPOIDCConfigWriteModel) NewChangedEvent(
authorizationEndpoint,
tokenEndpoint,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
idpDisplayNameMapping,
userNameMapping domain.OIDCMappingField,
scopes ...string,
+2 -2
View File
@@ -279,8 +279,8 @@ func (h plainHasher) Verify(encoded, password string) (verifier.Result, error) {
//
// With `x` set to "foo", the following encoded string would be produced by Hash:
// $plain$foo$password
func mockPasswordHasher(x string) *crypto.PasswordHasher {
return &crypto.PasswordHasher{
func mockPasswordHasher(x string) *crypto.Hasher {
return &crypto.Hasher{
Swapper: passwap.NewSwapper(plainHasher{x: x}),
Prefixes: []string{"$plain$"},
}
+11 -11
View File
@@ -63,7 +63,7 @@ func (wm *OrgOAuthIDPWriteModel) NewChangedEvent(
name,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
authorizationEndpoint,
tokenEndpoint,
userEndpoint,
@@ -173,7 +173,7 @@ func (wm *OrgOIDCIDPWriteModel) NewChangedEvent(
issuer,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
idTokenMapping bool,
options idp.Options,
@@ -350,7 +350,7 @@ func (wm *OrgAzureADIDPWriteModel) NewChangedEvent(
name,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
tenant string,
isEmailVerified bool,
@@ -426,7 +426,7 @@ func (wm *OrgGitHubIDPWriteModel) NewChangedEvent(
name,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) (*org.GitHubIDPChangedEvent, error) {
@@ -492,7 +492,7 @@ func (wm *OrgGitHubEnterpriseIDPWriteModel) NewChangedEvent(
name,
clientID string,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
authorizationEndpoint,
tokenEndpoint,
userEndpoint string,
@@ -571,7 +571,7 @@ func (wm *OrgGitLabIDPWriteModel) NewChangedEvent(
name,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) (*org.GitLabIDPChangedEvent, error) {
@@ -637,7 +637,7 @@ func (wm *OrgGitLabSelfHostedIDPWriteModel) NewChangedEvent(
issuer,
clientID string,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) (*org.GitLabSelfHostedIDPChangedEvent, error) {
@@ -705,7 +705,7 @@ func (wm *OrgGoogleIDPWriteModel) NewChangedEvent(
name,
clientID,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) (*org.GoogleIDPChangedEvent, error) {
@@ -777,7 +777,7 @@ func (wm *OrgLDAPIDPWriteModel) NewChangedEvent(
userObjectClasses []string,
userFilters []string,
timeout time.Duration,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
attributes idp.LDAPAttributes,
options idp.Options,
) (*org.LDAPIDPChangedEvent, error) {
@@ -858,7 +858,7 @@ func (wm *OrgAppleIDPWriteModel) NewChangedEvent(
teamID,
keyID string,
privateKey []byte,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
scopes []string,
options idp.Options,
) (*org.AppleIDPChangedEvent, error) {
@@ -924,7 +924,7 @@ func (wm *OrgSAMLIDPWriteModel) NewChangedEvent(
metadata,
key,
certificate []byte,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
binding string,
withSignedRequest bool,
options idp.Options,
@@ -92,7 +92,7 @@ func (wm *IDPOIDCConfigWriteModel) NewChangedEvent(
authorizationEndpoint,
tokenEndpoint,
clientSecretString string,
secretCrypto crypto.Crypto,
secretCrypto crypto.EncryptionAlgorithm,
idpDisplayNameMapping,
userNameMapping domain.OIDCMappingField,
scopes ...string,
+7 -7
View File
@@ -1260,7 +1260,7 @@ func TestCommandSide_SetUpOrg(t *testing.T) {
type fields struct {
eventstore func(t *testing.T) *eventstore.Eventstore
idGenerator id.Generator
newCode cryptoCodeFunc
newCode encrypedCodeFunc
keyAlgorithm crypto.EncryptionAlgorithm
}
type args struct {
@@ -1437,7 +1437,7 @@ func TestCommandSide_SetUpOrg(t *testing.T) {
),
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "orgID", "userID"),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: authz.WithRequestedDomain(context.Background(), "iam-domain"),
@@ -1616,7 +1616,7 @@ func TestCommandSide_SetUpOrg(t *testing.T) {
),
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "orgID", "userID", "tokenID"),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
args: args{
@@ -1669,10 +1669,10 @@ func TestCommandSide_SetUpOrg(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
idGenerator: tt.fields.idGenerator,
newCode: tt.fields.newCode,
keyAlgorithm: tt.fields.keyAlgorithm,
eventstore: tt.fields.eventstore(t),
idGenerator: tt.fields.idGenerator,
newEncryptedCode: tt.fields.newCode,
keyAlgorithm: tt.fields.keyAlgorithm,
zitadelRoles: []authz.RoleMapping{
{
Role: domain.RoleOrgOwner,
+2 -2
View File
@@ -16,6 +16,6 @@ type Phone struct {
ReturnCode bool
}
func (c *Commands) newPhoneCode(ctx context.Context, filter preparation.FilterToQueryReducer, alg crypto.EncryptionAlgorithm) (*CryptoCode, error) {
return c.newCode(ctx, filter, domain.SecretGeneratorTypeVerifyPhoneCode, alg)
func (c *Commands) newPhoneCode(ctx context.Context, filter preparation.FilterToQueryReducer, alg crypto.EncryptionAlgorithm) (*EncryptedCode, error) {
return c.newEncryptedCode(ctx, filter, domain.SecretGeneratorTypeVerifyPhoneCode, alg)
}
+2 -2
View File
@@ -22,7 +22,7 @@ type CommandVerifier interface {
Validate(eventstore.Command) bool
}
// AssertValidation checks if the validation works as inteded
// AssertValidation checks if the validation works as intended
func AssertValidation(t *testing.T, ctx context.Context, validation preparation.Validation, filter preparation.FilterToQueryReducer, want Want) {
t.Helper()
@@ -51,7 +51,7 @@ func AssertValidation(t *testing.T, ctx context.Context, validation preparation.
for i, cmd := range want.Commands {
if v, ok := cmd.(CommandVerifier); ok {
if verified := v.Validate(cmds[i]); !verified {
t.Errorf("verification failed on command: = %v, want %v", cmds[i], cmd)
t.Errorf("verification failed on command: =\n%v\nwant\n%v", cmds[i], cmd)
}
continue
}
-6
View File
@@ -3,8 +3,6 @@ package command
import (
"context"
"github.com/zitadel/zitadel/internal/command/preparation"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/repository/project"
"github.com/zitadel/zitadel/internal/zerrors"
@@ -16,10 +14,6 @@ type AddApp struct {
Name string
}
func (c *Commands) newAppClientSecret(ctx context.Context, filter preparation.FilterToQueryReducer, alg crypto.HashAlgorithm) (*CryptoCode, error) {
return c.newCode(ctx, filter, domain.SecretGeneratorTypeAppSecret, alg)
}
func (c *Commands) ChangeApplication(ctx context.Context, projectID string, appChange domain.Application, resourceOwner string) (*domain.ObjectDetails, error) {
if projectID == "" || appChange.GetAppID() == "" || appChange.GetApplicationName() == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-4m9vS", "Errors.Project.App.Invalid")
+51 -29
View File
@@ -4,10 +4,7 @@ import (
"context"
"strings"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/command/preparation"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
project_repo "github.com/zitadel/zitadel/internal/repository/project"
@@ -20,11 +17,11 @@ type addAPIApp struct {
AuthMethodType domain.APIAuthMethodType
ClientID string
ClientSecret *crypto.CryptoValue
EncodedHash string
ClientSecretPlain string
}
func (c *Commands) AddAPIAppCommand(app *addAPIApp, clientSecretAlg crypto.HashAlgorithm) preparation.Validation {
func (c *Commands) AddAPIAppCommand(app *addAPIApp) preparation.Validation {
return func() (preparation.CreateCommands, error) {
if app.ID == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "PROJE-XHsKt", "Errors.Invalid.Argument")
@@ -44,11 +41,10 @@ func (c *Commands) AddAPIAppCommand(app *addAPIApp, clientSecretAlg crypto.HashA
}
if app.AuthMethodType == domain.APIAuthMethodTypeBasic {
code, err := c.newAppClientSecret(ctx, filter, clientSecretAlg)
app.EncodedHash, app.ClientSecretPlain, err = c.newHashedSecret(ctx, filter)
if err != nil {
return nil, err
}
app.ClientSecret, app.ClientSecretPlain = code.Crypted, code.Plain
}
return []eventstore.Command{
@@ -63,7 +59,7 @@ func (c *Commands) AddAPIAppCommand(app *addAPIApp, clientSecretAlg crypto.HashA
&app.Aggregate.Aggregate,
app.ID,
app.ClientID,
app.ClientSecret,
app.EncodedHash,
app.AuthMethodType,
),
}, nil
@@ -71,7 +67,7 @@ func (c *Commands) AddAPIAppCommand(app *addAPIApp, clientSecretAlg crypto.HashA
}
}
func (c *Commands) AddAPIApplicationWithID(ctx context.Context, apiApp *domain.APIApp, resourceOwner, appID string, appSecretGenerator crypto.Generator) (_ *domain.APIApp, err error) {
func (c *Commands) AddAPIApplicationWithID(ctx context.Context, apiApp *domain.APIApp, resourceOwner, appID string) (_ *domain.APIApp, err error) {
existingAPI, err := c.getAPIAppWriteModel(ctx, apiApp.AggregateID, appID, resourceOwner)
if err != nil {
return nil, err
@@ -84,10 +80,10 @@ func (c *Commands) AddAPIApplicationWithID(ctx context.Context, apiApp *domain.A
return nil, zerrors.ThrowPreconditionFailed(err, "PROJECT-9fnsa", "Errors.Project.NotFound")
}
return c.addAPIApplicationWithID(ctx, apiApp, resourceOwner, project, appID, appSecretGenerator)
return c.addAPIApplicationWithID(ctx, apiApp, resourceOwner, project, appID)
}
func (c *Commands) AddAPIApplication(ctx context.Context, apiApp *domain.APIApp, resourceOwner string, appSecretGenerator crypto.Generator) (_ *domain.APIApp, err error) {
func (c *Commands) AddAPIApplication(ctx context.Context, apiApp *domain.APIApp, resourceOwner string) (_ *domain.APIApp, err error) {
if apiApp == nil || apiApp.AggregateID == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "PROJECT-5m9E", "Errors.Project.App.Invalid")
}
@@ -105,10 +101,10 @@ func (c *Commands) AddAPIApplication(ctx context.Context, apiApp *domain.APIApp,
return nil, err
}
return c.addAPIApplicationWithID(ctx, apiApp, resourceOwner, project, appID, appSecretGenerator)
return c.addAPIApplicationWithID(ctx, apiApp, resourceOwner, project, appID)
}
func (c *Commands) addAPIApplicationWithID(ctx context.Context, apiApp *domain.APIApp, resourceOwner string, project *domain.Project, appID string, appSecretGenerator crypto.Generator) (_ *domain.APIApp, err error) {
func (c *Commands) addAPIApplicationWithID(ctx context.Context, apiApp *domain.APIApp, resourceOwner string, project *domain.Project, appID string) (_ *domain.APIApp, err error) {
apiApp.AppID = appID
addedApplication := NewAPIApplicationWriteModel(apiApp.AggregateID, resourceOwner)
@@ -118,12 +114,14 @@ func (c *Commands) addAPIApplicationWithID(ctx context.Context, apiApp *domain.A
project_repo.NewApplicationAddedEvent(ctx, projectAgg, apiApp.AppID, apiApp.AppName),
}
var stringPw string
var plain string
err = domain.SetNewClientID(apiApp, c.idGenerator, project)
if err != nil {
return nil, err
}
stringPw, err = domain.SetNewClientSecretIfNeeded(apiApp, appSecretGenerator)
plain, err = domain.SetNewClientSecretIfNeeded(apiApp, func() (string, string, error) {
return c.newHashedSecret(ctx, c.eventstore.Filter) //nolint:staticcheck
})
if err != nil {
return nil, err
}
@@ -131,7 +129,7 @@ func (c *Commands) addAPIApplicationWithID(ctx context.Context, apiApp *domain.A
projectAgg,
apiApp.AppID,
apiApp.ClientID,
apiApp.ClientSecret,
apiApp.EncodedHash,
apiApp.AuthMethodType))
addedApplication.AppID = apiApp.AppID
@@ -144,7 +142,7 @@ func (c *Commands) addAPIApplicationWithID(ctx context.Context, apiApp *domain.A
return nil, err
}
result := apiWriteModelToAPIConfig(addedApplication)
result.ClientSecretString = stringPw
result.ClientSecretString = plain
return result, nil
}
@@ -188,7 +186,7 @@ func (c *Commands) ChangeAPIApplication(ctx context.Context, apiApp *domain.APIA
return apiWriteModelToAPIConfig(existingAPI), nil
}
func (c *Commands) ChangeAPIApplicationSecret(ctx context.Context, projectID, appID, resourceOwner string, appSecretGenerator crypto.Generator) (*domain.APIApp, error) {
func (c *Commands) ChangeAPIApplicationSecret(ctx context.Context, projectID, appID, resourceOwner string) (*domain.APIApp, error) {
if projectID == "" || appID == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-99i83", "Errors.IDMissing")
}
@@ -203,14 +201,14 @@ func (c *Commands) ChangeAPIApplicationSecret(ctx context.Context, projectID, ap
if !existingAPI.IsAPI() {
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-aeH4", "Errors.Project.App.IsNotAPI")
}
cryptoSecret, stringPW, err := domain.NewClientSecret(appSecretGenerator)
encodedHash, plain, err := c.newHashedSecret(ctx, c.eventstore.Filter) //nolint:staticcheck
if err != nil {
return nil, err
}
projectAgg := ProjectAggregateFromWriteModel(&existingAPI.WriteModel)
pushedEvents, err := c.eventstore.Push(ctx, project_repo.NewAPIConfigSecretChangedEvent(ctx, projectAgg, appID, cryptoSecret))
pushedEvents, err := c.eventstore.Push(ctx, project_repo.NewAPIConfigSecretChangedEvent(ctx, projectAgg, appID, encodedHash))
if err != nil {
return nil, err
}
@@ -220,7 +218,7 @@ func (c *Commands) ChangeAPIApplicationSecret(ctx context.Context, projectID, ap
}
result := apiWriteModelToAPIConfig(existingAPI)
result.ClientSecretString = stringPW
result.ClientSecretString = plain
return result, err
}
@@ -233,26 +231,35 @@ func (c *Commands) VerifyAPIClientSecret(ctx context.Context, projectID, appID,
return err
}
if !app.State.Exists() {
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-DFnbf", "Errors.Project.App.NoExisting")
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-DFnbf", "Errors.Project.App.NotExisting")
}
if !app.IsAPI() {
return zerrors.ThrowInvalidArgument(nil, "COMMAND-Bf3fw", "Errors.Project.App.IsNotAPI")
}
if app.ClientSecret == nil {
if app.HashedSecret == "" {
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-D3t5g", "Errors.Project.App.APIConfigInvalid")
}
projectAgg := ProjectAggregateFromWriteModel(&app.WriteModel)
ctx, spanPasswordComparison := tracing.NewNamedSpan(ctx, "crypto.CompareHash")
err = crypto.CompareHash(app.ClientSecret, []byte(secret), c.codeAlg)
ctx, spanPasswordComparison := tracing.NewNamedSpan(ctx, "passwap.Verify")
updated, err := c.secretHasher.Verify(app.HashedSecret, secret)
spanPasswordComparison.EndWithError(err)
if err == nil {
_, err = c.eventstore.Push(ctx, project_repo.NewAPIConfigSecretCheckSucceededEvent(ctx, projectAgg, app.AppID))
c.apiSecretCheckSucceeded(ctx, projectAgg, app.AppID, updated)
return err
}
_, err = c.eventstore.Push(ctx, project_repo.NewAPIConfigSecretCheckFailedEvent(ctx, projectAgg, app.AppID))
logging.Log("COMMAND-g3f12").OnError(err).Error("could not push event APIClientSecretCheckFailed")
return zerrors.ThrowInvalidArgument(nil, "COMMAND-SADfg", "Errors.Project.App.ClientSecretInvalid")
c.apiSecretCheckFailed(ctx, projectAgg, app.AppID)
return zerrors.ThrowInvalidArgument(err, "COMMAND-SADfg", "Errors.Project.App.ClientSecretInvalid")
}
func (c *Commands) APISecretCheckSucceeded(ctx context.Context, appID, projectID, resourceOwner, updated string) {
agg := project_repo.NewAggregate(projectID, resourceOwner)
c.apiSecretCheckSucceeded(ctx, &agg.Aggregate, appID, updated)
}
func (c *Commands) APISecretCheckFailed(ctx context.Context, appID, projectID, resourceOwner string) {
agg := project_repo.NewAggregate(projectID, resourceOwner)
c.apiSecretCheckFailed(ctx, &agg.Aggregate, appID)
}
func (c *Commands) getAPIAppWriteModel(ctx context.Context, projectID, appID, resourceOwner string) (*APIApplicationWriteModel, error) {
@@ -263,3 +270,18 @@ func (c *Commands) getAPIAppWriteModel(ctx context.Context, projectID, appID, re
}
return appWriteModel, nil
}
func (c *Commands) apiSecretCheckSucceeded(ctx context.Context, agg *eventstore.Aggregate, appID, updated string) {
cmds := append(
make([]eventstore.Command, 0, 2),
project_repo.NewAPIConfigSecretCheckSucceededEvent(ctx, agg, appID),
)
if updated != "" {
cmds = append(cmds, project_repo.NewAPIConfigSecretHashUpdatedEvent(ctx, agg, appID, updated))
}
c.asyncPush(ctx, cmds...)
}
func (c *Commands) apiSecretCheckFailed(ctx context.Context, agg *eventstore.Aggregate, appID string) {
c.asyncPush(ctx, project_repo.NewAPIConfigSecretCheckFailedEvent(ctx, agg, appID))
}
@@ -15,7 +15,7 @@ type APIApplicationWriteModel struct {
AppID string
AppName string
ClientID string
ClientSecret *crypto.CryptoValue
HashedSecret string
ClientSecretString string
AuthMethodType domain.APIAuthMethodType
State domain.AppState
@@ -83,6 +83,11 @@ func (wm *APIApplicationWriteModel) AppendEvents(events ...eventstore.Event) {
continue
}
wm.WriteModel.AppendEvents(e)
case *project.APIConfigSecretHashUpdatedEvent:
if e.AppID != wm.AppID {
continue
}
wm.WriteModel.AppendEvents(e)
case *project.ProjectRemovedEvent:
wm.WriteModel.AppendEvents(e)
}
@@ -114,7 +119,9 @@ func (wm *APIApplicationWriteModel) Reduce() error {
case *project.APIConfigChangedEvent:
wm.appendChangeAPIEvent(e)
case *project.APIConfigSecretChangedEvent:
wm.ClientSecret = e.ClientSecret
wm.HashedSecret = crypto.SecretOrEncodedHash(e.ClientSecret, e.HashedSecret)
case *project.APIConfigSecretHashUpdatedEvent:
wm.HashedSecret = e.HashedSecret
case *project.ProjectRemovedEvent:
wm.State = domain.AppStateRemoved
}
@@ -125,7 +132,7 @@ func (wm *APIApplicationWriteModel) Reduce() error {
func (wm *APIApplicationWriteModel) appendAddAPIEvent(e *project.APIConfigAddedEvent) {
wm.api = true
wm.ClientID = e.ClientID
wm.ClientSecret = e.ClientSecret
wm.HashedSecret = crypto.SecretOrEncodedHash(e.ClientSecret, e.HashedSecret)
wm.AuthMethodType = e.AuthMethodType
}
@@ -150,8 +157,9 @@ func (wm *APIApplicationWriteModel) Query() *eventstore.SearchQueryBuilder {
project.APIConfigAddedType,
project.APIConfigChangedType,
project.APIConfigSecretChangedType,
project.ProjectRemovedType).
Builder()
project.APIConfigSecretHashUpdatedType,
project.ProjectRemovedType,
).Builder()
}
func (wm *APIApplicationWriteModel) NewChangedEvent(
+162 -88
View File
@@ -2,9 +2,13 @@ package command
import (
"context"
"io"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/passwap"
"github.com/zitadel/passwap/bcrypt"
"github.com/zitadel/zitadel/internal/command/preparation"
"github.com/zitadel/zitadel/internal/crypto"
@@ -114,7 +118,7 @@ func TestAddAPIConfig(t *testing.T) {
project.NewAPIConfigAddedEvent(ctx, &agg.Aggregate,
"appID",
"clientID@project",
nil,
"",
domain.APIAuthMethodTypePrivateKeyJWT,
),
},
@@ -137,7 +141,6 @@ func TestAddAPIConfig(t *testing.T) {
},
AuthMethodType: domain.APIAuthMethodTypePrivateKeyJWT,
},
nil,
), tt.args.filter, tt.want)
})
}
@@ -145,14 +148,13 @@ func TestAddAPIConfig(t *testing.T) {
func TestCommandSide_AddAPIApplication(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
idGenerator id.Generator
}
type args struct {
ctx context.Context
apiApp *domain.APIApp
resourceOwner string
secretGenerator crypto.Generator
ctx context.Context
apiApp *domain.APIApp
resourceOwner string
}
type res struct {
want *domain.APIApp
@@ -167,9 +169,7 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
{
name: "no aggregate id, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -183,8 +183,7 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
{
name: "project not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -206,8 +205,7 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
{
name: "invalid app, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewProjectAddedEvent(context.Background(),
@@ -236,8 +234,7 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
{
name: "create api app basic, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewProjectAddedEvent(context.Background(),
@@ -256,12 +253,7 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
&project.NewAggregate("project1", "org1").Aggregate,
"app1",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
domain.APIAuthMethodTypeBasic),
),
),
@@ -276,8 +268,7 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
AppName: "app",
AuthMethodType: domain.APIAuthMethodTypeBasic,
},
resourceOwner: "org1",
secretGenerator: GetMockSecretGenerator(t),
resourceOwner: "org1",
},
res: res{
want: &domain.APIApp{
@@ -288,7 +279,7 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
AppID: "app1",
AppName: "app",
ClientID: "client1@project",
ClientSecretString: "a",
ClientSecretString: "secret",
AuthMethodType: domain.APIAuthMethodTypeBasic,
State: domain.AppStateActive,
},
@@ -297,8 +288,7 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
{
name: "create api app jwt, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewProjectAddedEvent(context.Background(),
@@ -317,7 +307,7 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
&project.NewAggregate("project1", "org1").Aggregate,
"app1",
"client1@project",
nil,
"",
domain.APIAuthMethodTypePrivateKeyJWT),
),
),
@@ -352,10 +342,14 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
idGenerator: tt.fields.idGenerator,
eventstore: tt.fields.eventstore(t),
idGenerator: tt.fields.idGenerator,
newHashedSecret: mockHashedSecret("secret"),
defaultSecretGenerators: &SecretGenerators{
ClientSecret: emptyConfig,
},
}
got, err := r.AddAPIApplication(tt.args.ctx, tt.args.apiApp, tt.args.resourceOwner, tt.args.secretGenerator)
got, err := r.AddAPIApplication(tt.args.ctx, tt.args.apiApp, tt.args.resourceOwner)
if tt.res.err == nil {
assert.NoError(t, err)
}
@@ -371,7 +365,7 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
func TestCommandSide_ChangeAPIApplication(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type args struct {
ctx context.Context
@@ -391,9 +385,7 @@ func TestCommandSide_ChangeAPIApplication(t *testing.T) {
{
name: "missing appid, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -414,9 +406,7 @@ func TestCommandSide_ChangeAPIApplication(t *testing.T) {
{
name: "missing aggregateid, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -437,8 +427,7 @@ func TestCommandSide_ChangeAPIApplication(t *testing.T) {
{
name: "app not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -460,8 +449,7 @@ func TestCommandSide_ChangeAPIApplication(t *testing.T) {
{
name: "no changes, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(),
@@ -475,7 +463,7 @@ func TestCommandSide_ChangeAPIApplication(t *testing.T) {
&project.NewAggregate("project1", "org1").Aggregate,
"app1",
"client1@project",
nil,
"",
domain.APIAuthMethodTypePrivateKeyJWT),
),
),
@@ -500,8 +488,7 @@ func TestCommandSide_ChangeAPIApplication(t *testing.T) {
{
name: "change api app, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(),
@@ -515,12 +502,7 @@ func TestCommandSide_ChangeAPIApplication(t *testing.T) {
&project.NewAggregate("project1", "org1").Aggregate,
"app1",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
domain.APIAuthMethodTypeBasic),
),
),
@@ -563,7 +545,11 @@ func TestCommandSide_ChangeAPIApplication(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
newHashedSecret: mockHashedSecret("secret"),
defaultSecretGenerators: &SecretGenerators{
ClientSecret: emptyConfig,
},
}
got, err := r.ChangeAPIApplication(tt.args.ctx, tt.args.apiApp, tt.args.resourceOwner)
if tt.res.err == nil {
@@ -581,14 +567,13 @@ func TestCommandSide_ChangeAPIApplication(t *testing.T) {
func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(*testing.T) *eventstore.Eventstore
}
type args struct {
ctx context.Context
appID string
projectID string
resourceOwner string
secretGenerator crypto.Generator
ctx context.Context
appID string
projectID string
resourceOwner string
}
type res struct {
want *domain.APIApp
@@ -603,9 +588,7 @@ func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
{
name: "no projectid, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -619,9 +602,7 @@ func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
{
name: "no appid, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -636,8 +617,7 @@ func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
{
name: "app not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -654,8 +634,7 @@ func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
{
name: "change secret, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(),
@@ -669,12 +648,7 @@ func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
&project.NewAggregate("project1", "org1").Aggregate,
"app1",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
domain.APIAuthMethodTypeBasic),
),
),
@@ -682,22 +656,16 @@ func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
project.NewAPIConfigSecretChangedEvent(context.Background(),
&project.NewAggregate("project1", "org1").Aggregate,
"app1",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
),
),
),
},
args: args{
ctx: context.Background(),
projectID: "project1",
appID: "app1",
resourceOwner: "org1",
secretGenerator: GetMockSecretGenerator(t),
ctx: context.Background(),
projectID: "project1",
appID: "app1",
resourceOwner: "org1",
},
res: res{
want: &domain.APIApp{
@@ -708,7 +676,7 @@ func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
AppID: "app1",
AppName: "app",
ClientID: "client1@project",
ClientSecretString: "a",
ClientSecretString: "secret",
AuthMethodType: domain.APIAuthMethodTypeBasic,
State: domain.AppStateActive,
},
@@ -718,9 +686,13 @@ func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
newHashedSecret: mockHashedSecret("secret"),
defaultSecretGenerators: &SecretGenerators{
ClientSecret: emptyConfig,
},
}
got, err := r.ChangeAPIApplicationSecret(tt.args.ctx, tt.args.projectID, tt.args.appID, tt.args.resourceOwner, tt.args.secretGenerator)
got, err := r.ChangeAPIApplicationSecret(tt.args.ctx, tt.args.projectID, tt.args.appID, tt.args.resourceOwner)
if tt.res.err == nil {
assert.NoError(t, err)
}
@@ -745,3 +717,105 @@ func newAPIAppChangedEvent(ctx context.Context, appID, projectID, resourceOwner
)
return event
}
func TestCommands_VerifyAPIClientSecret(t *testing.T) {
hasher := &crypto.Hasher{
Swapper: passwap.NewSwapper(bcrypt.New(bcrypt.MinCost)),
}
hashedSecret, err := hasher.Hash("secret")
require.NoError(t, err)
agg := project.NewAggregate("projectID", "orgID")
tests := []struct {
name string
secret string
eventstore func(*testing.T) *eventstore.Eventstore
wantErr error
}{
{
name: "filter error",
eventstore: expectEventstore(
expectFilterError(io.ErrClosedPipe),
),
wantErr: io.ErrClosedPipe,
},
{
name: "app not exists",
eventstore: expectEventstore(
expectFilter(),
),
wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-DFnbf", "Errors.Project.App.NotExisting"),
},
{
name: "wrong app type",
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
),
),
),
wantErr: zerrors.ThrowInvalidArgument(nil, "COMMAND-Bf3fw", "Errors.Project.App.IsNotAPI"),
},
{
name: "no secret set",
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
),
eventFromEventPusher(
project.NewAPIConfigAddedEvent(context.Background(), &agg.Aggregate, "appID", "clientID", "", domain.APIAuthMethodTypePrivateKeyJWT),
),
),
),
wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-D3t5g", "Errors.Project.App.APIConfigInvalid"),
},
{
name: "check succeeded",
secret: "secret",
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
),
eventFromEventPusher(
project.NewAPIConfigAddedEvent(context.Background(), &agg.Aggregate, "appID", "clientID", hashedSecret, domain.APIAuthMethodTypePrivateKeyJWT),
),
),
expectPush(
project.NewAPIConfigSecretCheckSucceededEvent(context.Background(), &agg.Aggregate, "appID"),
),
),
},
{
name: "check failed",
secret: "wrong!",
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
),
eventFromEventPusher(
project.NewAPIConfigAddedEvent(context.Background(), &agg.Aggregate, "appID", "clientID", hashedSecret, domain.APIAuthMethodTypePrivateKeyJWT),
),
),
expectPush(
project.NewAPIConfigSecretCheckFailedEvent(context.Background(), &agg.Aggregate, "appID"),
),
),
wantErr: zerrors.ThrowInvalidArgument(err, "COMMAND-SADfg", "Errors.Project.App.ClientSecretInvalid"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Commands{
eventstore: tt.eventstore(t),
secretHasher: hasher,
}
err := c.VerifyAPIClientSecret(context.Background(), "projectID", "appID", tt.secret)
c.jobs.Wait()
require.ErrorIs(t, err, tt.wantErr)
})
}
}
@@ -6,7 +6,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
@@ -117,12 +116,7 @@ func TestCommandSide_AddAPIApplicationKey(t *testing.T) {
&project.NewAggregate("project1", "org1").Aggregate,
"app1",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
domain.APIAuthMethodTypeBasic),
),
),
@@ -163,12 +157,7 @@ func TestCommandSide_AddAPIApplicationKey(t *testing.T) {
&project.NewAggregate("project1", "org1").Aggregate,
"app1",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
domain.APIAuthMethodTypeBasic),
),
),
+51 -30
View File
@@ -5,11 +5,8 @@ import (
"strings"
"time"
"github.com/zitadel/logging"
http_util "github.com/zitadel/zitadel/internal/api/http"
"github.com/zitadel/zitadel/internal/command/preparation"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
project_repo "github.com/zitadel/zitadel/internal/repository/project"
@@ -36,12 +33,12 @@ type addOIDCApp struct {
SkipSuccessPageForNativeApp bool
ClientID string
ClientSecret *crypto.CryptoValue
ClientSecret string
ClientSecretPlain string
}
// AddOIDCAppCommand prepares the commands to add an oidc app. The ClientID will be set during the CreateCommands
func (c *Commands) AddOIDCAppCommand(app *addOIDCApp, clientSecretAlg crypto.HashAlgorithm) preparation.Validation {
func (c *Commands) AddOIDCAppCommand(app *addOIDCApp) preparation.Validation {
return func() (preparation.CreateCommands, error) {
if app.ID == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "PROJE-NnavI", "Errors.Invalid.Argument")
@@ -77,11 +74,10 @@ func (c *Commands) AddOIDCAppCommand(app *addOIDCApp, clientSecretAlg crypto.Has
}
if app.AuthMethodType == domain.OIDCAuthMethodTypeBasic || app.AuthMethodType == domain.OIDCAuthMethodTypePost {
code, err := c.newAppClientSecret(ctx, filter, clientSecretAlg)
app.ClientSecret, app.ClientSecretPlain, err = c.newHashedSecret(ctx, filter)
if err != nil {
return nil, err
}
app.ClientSecret, app.ClientSecretPlain = code.Crypted, code.Plain
}
return []eventstore.Command{
@@ -118,7 +114,7 @@ func (c *Commands) AddOIDCAppCommand(app *addOIDCApp, clientSecretAlg crypto.Has
}
}
func (c *Commands) AddOIDCApplicationWithID(ctx context.Context, oidcApp *domain.OIDCApp, resourceOwner, appID string, appSecretGenerator crypto.Generator) (_ *domain.OIDCApp, err error) {
func (c *Commands) AddOIDCApplicationWithID(ctx context.Context, oidcApp *domain.OIDCApp, resourceOwner, appID string) (_ *domain.OIDCApp, err error) {
existingApp, err := c.getOIDCAppWriteModel(ctx, oidcApp.AggregateID, appID, resourceOwner)
if err != nil {
return nil, err
@@ -132,10 +128,10 @@ func (c *Commands) AddOIDCApplicationWithID(ctx context.Context, oidcApp *domain
return nil, zerrors.ThrowPreconditionFailed(err, "PROJECT-3m9s2", "Errors.Project.NotFound")
}
return c.addOIDCApplicationWithID(ctx, oidcApp, resourceOwner, project, appID, appSecretGenerator)
return c.addOIDCApplicationWithID(ctx, oidcApp, resourceOwner, project, appID)
}
func (c *Commands) AddOIDCApplication(ctx context.Context, oidcApp *domain.OIDCApp, resourceOwner string, appSecretGenerator crypto.Generator) (_ *domain.OIDCApp, err error) {
func (c *Commands) AddOIDCApplication(ctx context.Context, oidcApp *domain.OIDCApp, resourceOwner string) (_ *domain.OIDCApp, err error) {
if oidcApp == nil || oidcApp.AggregateID == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "PROJECT-34Fm0", "Errors.Project.App.Invalid")
}
@@ -153,11 +149,10 @@ func (c *Commands) AddOIDCApplication(ctx context.Context, oidcApp *domain.OIDCA
return nil, err
}
return c.addOIDCApplicationWithID(ctx, oidcApp, resourceOwner, project, appID, appSecretGenerator)
return c.addOIDCApplicationWithID(ctx, oidcApp, resourceOwner, project, appID)
}
func (c *Commands) addOIDCApplicationWithID(ctx context.Context, oidcApp *domain.OIDCApp, resourceOwner string, project *domain.Project, appID string, appSecretGenerator crypto.Generator) (_ *domain.OIDCApp, err error) {
func (c *Commands) addOIDCApplicationWithID(ctx context.Context, oidcApp *domain.OIDCApp, resourceOwner string, project *domain.Project, appID string) (_ *domain.OIDCApp, err error) {
addedApplication := NewOIDCApplicationWriteModel(oidcApp.AggregateID, resourceOwner)
projectAgg := ProjectAggregateFromWriteModel(&addedApplication.WriteModel)
@@ -167,12 +162,14 @@ func (c *Commands) addOIDCApplicationWithID(ctx context.Context, oidcApp *domain
project_repo.NewApplicationAddedEvent(ctx, projectAgg, oidcApp.AppID, oidcApp.AppName),
}
var stringPw string
var plain string
err = domain.SetNewClientID(oidcApp, c.idGenerator, project)
if err != nil {
return nil, err
}
stringPw, err = domain.SetNewClientSecretIfNeeded(oidcApp, appSecretGenerator)
plain, err = domain.SetNewClientSecretIfNeeded(oidcApp, func() (string, string, error) {
return c.newHashedSecret(ctx, c.eventstore.Filter) //nolint:staticcheck
})
if err != nil {
return nil, err
}
@@ -181,7 +178,7 @@ func (c *Commands) addOIDCApplicationWithID(ctx context.Context, oidcApp *domain
oidcApp.OIDCVersion,
oidcApp.AppID,
oidcApp.ClientID,
oidcApp.ClientSecret,
oidcApp.EncodedHash,
trimStringSliceWhiteSpaces(oidcApp.RedirectUris),
oidcApp.ResponseTypes,
oidcApp.GrantTypes,
@@ -208,7 +205,7 @@ func (c *Commands) addOIDCApplicationWithID(ctx context.Context, oidcApp *domain
return nil, err
}
result := oidcWriteModelToOIDCConfig(addedApplication)
result.ClientSecretString = stringPw
result.ClientSecretString = plain
result.FillCompliance()
return result, nil
}
@@ -270,7 +267,7 @@ func (c *Commands) ChangeOIDCApplication(ctx context.Context, oidc *domain.OIDCA
return result, nil
}
func (c *Commands) ChangeOIDCApplicationSecret(ctx context.Context, projectID, appID, resourceOwner string, appSecretGenerator crypto.Generator) (*domain.OIDCApp, error) {
func (c *Commands) ChangeOIDCApplicationSecret(ctx context.Context, projectID, appID, resourceOwner string) (*domain.OIDCApp, error) {
if projectID == "" || appID == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-99i83", "Errors.IDMissing")
}
@@ -285,14 +282,14 @@ func (c *Commands) ChangeOIDCApplicationSecret(ctx context.Context, projectID, a
if !existingOIDC.IsOIDC() {
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-Ghrh3", "Errors.Project.App.IsNotOIDC")
}
cryptoSecret, stringPW, err := domain.NewClientSecret(appSecretGenerator)
encodedHash, plain, err := c.newHashedSecret(ctx, c.eventstore.Filter) //nolint:staticcheck
if err != nil {
return nil, err
}
projectAgg := ProjectAggregateFromWriteModel(&existingOIDC.WriteModel)
pushedEvents, err := c.eventstore.Push(ctx, project_repo.NewOIDCConfigSecretChangedEvent(ctx, projectAgg, appID, cryptoSecret))
pushedEvents, err := c.eventstore.Push(ctx, project_repo.NewOIDCConfigSecretChangedEvent(ctx, projectAgg, appID, encodedHash))
if err != nil {
return nil, err
}
@@ -302,7 +299,7 @@ func (c *Commands) ChangeOIDCApplicationSecret(ctx context.Context, projectID, a
}
result := oidcWriteModelToOIDCConfig(existingOIDC)
result.ClientSecretString = stringPW
result.ClientSecretString = plain
return result, err
}
@@ -315,26 +312,35 @@ func (c *Commands) VerifyOIDCClientSecret(ctx context.Context, projectID, appID,
return err
}
if !app.State.Exists() {
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-D6hba", "Errors.Project.App.NotExisting")
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-D8hba", "Errors.Project.App.NotExisting")
}
if !app.IsOIDC() {
return zerrors.ThrowInvalidArgument(nil, "COMMAND-BHgn2", "Errors.Project.App.IsNotOIDC")
}
if app.ClientSecret == nil {
if app.HashedSecret == "" {
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-D6hba", "Errors.Project.App.OIDCConfigInvalid")
}
projectAgg := ProjectAggregateFromWriteModel(&app.WriteModel)
ctx, spanPasswordComparison := tracing.NewNamedSpan(ctx, "crypto.CompareHash")
err = crypto.CompareHash(app.ClientSecret, []byte(secret), c.codeAlg)
ctx, spanPasswordComparison := tracing.NewNamedSpan(ctx, "passwap.Verify")
updated, err := c.secretHasher.Verify(app.HashedSecret, secret)
spanPasswordComparison.EndWithError(err)
if err == nil {
_, err = c.eventstore.Push(ctx, project_repo.NewOIDCConfigSecretCheckSucceededEvent(ctx, projectAgg, app.AppID))
return err
c.oidcSecretCheckSucceeded(ctx, projectAgg, appID, updated)
return nil
}
_, err = c.eventstore.Push(ctx, project_repo.NewOIDCConfigSecretCheckFailedEvent(ctx, projectAgg, app.AppID))
logging.OnError(err).Error("could not push event OIDCClientSecretCheckFailed")
return zerrors.ThrowInvalidArgument(nil, "COMMAND-Bz542", "Errors.Project.App.ClientSecretInvalid")
c.oidcSecretCheckFailed(ctx, projectAgg, appID)
return zerrors.ThrowInvalidArgument(err, "COMMAND-Bz542", "Errors.Project.App.ClientSecretInvalid")
}
func (c *Commands) OIDCSecretCheckSucceeded(ctx context.Context, appID, projectID, resourceOwner, updated string) {
agg := project_repo.NewAggregate(projectID, resourceOwner)
c.oidcSecretCheckSucceeded(ctx, &agg.Aggregate, appID, updated)
}
func (c *Commands) OIDCSecretCheckFailed(ctx context.Context, appID, projectID, resourceOwner string) {
agg := project_repo.NewAggregate(projectID, resourceOwner)
c.oidcSecretCheckFailed(ctx, &agg.Aggregate, appID)
}
func (c *Commands) getOIDCAppWriteModel(ctx context.Context, projectID, appID, resourceOwner string) (*OIDCApplicationWriteModel, error) {
@@ -366,3 +372,18 @@ func trimStringSliceWhiteSpaces(slice []string) []string {
}
return slice
}
func (c *Commands) oidcSecretCheckSucceeded(ctx context.Context, agg *eventstore.Aggregate, appID, updated string) {
cmds := append(
make([]eventstore.Command, 0, 2),
project_repo.NewOIDCConfigSecretCheckSucceededEvent(ctx, agg, appID),
)
if updated != "" {
cmds = append(cmds, project_repo.NewOIDCConfigSecretHashUpdatedEvent(ctx, agg, appID, updated))
}
c.asyncPush(ctx, cmds...)
}
func (c *Commands) oidcSecretCheckFailed(ctx context.Context, agg *eventstore.Aggregate, appID string) {
c.asyncPush(ctx, project_repo.NewOIDCConfigSecretCheckFailedEvent(ctx, agg, appID))
}
@@ -17,7 +17,7 @@ type OIDCApplicationWriteModel struct {
AppID string
AppName string
ClientID string
ClientSecret *crypto.CryptoValue
HashedSecret string
ClientSecretString string
RedirectUris []string
ResponseTypes []domain.OIDCResponseType
@@ -100,6 +100,11 @@ func (wm *OIDCApplicationWriteModel) AppendEvents(events ...eventstore.Event) {
continue
}
wm.WriteModel.AppendEvents(e)
case *project.OIDCConfigSecretHashUpdatedEvent:
if e.AppID != wm.AppID {
continue
}
wm.WriteModel.AppendEvents(e)
case *project.ProjectRemovedEvent:
wm.WriteModel.AppendEvents(e)
}
@@ -131,7 +136,9 @@ func (wm *OIDCApplicationWriteModel) Reduce() error {
case *project.OIDCConfigChangedEvent:
wm.appendChangeOIDCEvent(e)
case *project.OIDCConfigSecretChangedEvent:
wm.ClientSecret = e.ClientSecret
wm.HashedSecret = crypto.SecretOrEncodedHash(e.ClientSecret, e.HashedSecret)
case *project.OIDCConfigSecretHashUpdatedEvent:
wm.HashedSecret = e.HashedSecret
case *project.ProjectRemovedEvent:
wm.State = domain.AppStateRemoved
}
@@ -142,7 +149,7 @@ func (wm *OIDCApplicationWriteModel) Reduce() error {
func (wm *OIDCApplicationWriteModel) appendAddOIDCEvent(e *project.OIDCConfigAddedEvent) {
wm.oidc = true
wm.ClientID = e.ClientID
wm.ClientSecret = e.ClientSecret
wm.HashedSecret = crypto.SecretOrEncodedHash(e.ClientSecret, e.HashedSecret)
wm.RedirectUris = e.RedirectUris
wm.ResponseTypes = e.ResponseTypes
wm.GrantTypes = e.GrantTypes
@@ -223,8 +230,9 @@ func (wm *OIDCApplicationWriteModel) Query() *eventstore.SearchQueryBuilder {
project.OIDCConfigAddedType,
project.OIDCConfigChangedType,
project.OIDCConfigSecretChangedType,
project.ProjectRemovedType).
Builder()
project.OIDCConfigSecretHashUpdatedType,
project.ProjectRemovedType,
).Builder()
}
func (wm *OIDCApplicationWriteModel) NewChangedEvent(
+288 -99
View File
@@ -2,10 +2,14 @@ package command
import (
"context"
"io"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/passwap"
"github.com/zitadel/passwap/bcrypt"
"github.com/zitadel/zitadel/internal/command/preparation"
"github.com/zitadel/zitadel/internal/crypto"
@@ -23,9 +27,8 @@ func TestAddOIDCApp(t *testing.T) {
idGenerator id.Generator
}
type args struct {
app *addOIDCApp
clientSecretAlg crypto.HashAlgorithm
filter preparation.FilterToQueryReducer
app *addOIDCApp
filter preparation.FilterToQueryReducer
}
ctx := context.Background()
@@ -156,7 +159,7 @@ func TestAddOIDCApp(t *testing.T) {
domain.OIDCVersionV1,
"id",
"clientID@project",
nil,
"",
[]string{"https://test.ch"},
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
@@ -221,7 +224,7 @@ func TestAddOIDCApp(t *testing.T) {
domain.OIDCVersionV1,
"id",
"clientID@project",
nil,
"",
nil,
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
@@ -240,17 +243,85 @@ func TestAddOIDCApp(t *testing.T) {
},
},
},
{
name: "with secret",
fields: fields{
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "clientID"),
},
args: args{
app: &addOIDCApp{
AddApp: AddApp{
Aggregate: *agg,
ID: "id",
Name: "name",
},
GrantTypes: []domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
ResponseTypes: []domain.OIDCResponseType{domain.OIDCResponseTypeCode},
Version: domain.OIDCVersionV1,
ApplicationType: domain.OIDCApplicationTypeWeb,
AuthMethodType: domain.OIDCAuthMethodTypeBasic,
AccessTokenType: domain.OIDCTokenTypeBearer,
},
filter: NewMultiFilter().
Append(func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return []eventstore.Event{
project.NewProjectAddedEvent(
ctx,
&agg.Aggregate,
"project",
false,
false,
false,
domain.PrivateLabelingSettingUnspecified,
),
}, nil
}).
Filter(),
},
want: Want{
Commands: []eventstore.Command{
project.NewApplicationAddedEvent(ctx, &agg.Aggregate,
"id",
"name",
),
project.NewOIDCConfigAddedEvent(ctx, &agg.Aggregate,
domain.OIDCVersionV1,
"id",
"clientID@project",
"secret",
nil,
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
domain.OIDCApplicationTypeWeb,
domain.OIDCAuthMethodTypeBasic,
nil,
false,
domain.OIDCTokenTypeBearer,
false,
false,
false,
0,
nil,
false,
),
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := Commands{
idGenerator: tt.fields.idGenerator,
idGenerator: tt.fields.idGenerator,
newHashedSecret: mockHashedSecret("secret"),
defaultSecretGenerators: &SecretGenerators{
ClientSecret: emptyConfig,
},
}
AssertValidation(t,
context.Background(),
c.AddOIDCAppCommand(
tt.args.app,
tt.args.clientSecretAlg,
), tt.args.filter, tt.want)
})
}
@@ -258,14 +329,13 @@ func TestAddOIDCApp(t *testing.T) {
func TestCommandSide_AddOIDCApplication(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
idGenerator id.Generator
}
type args struct {
ctx context.Context
oidcApp *domain.OIDCApp
resourceOwner string
secretGenerator crypto.Generator
ctx context.Context
oidcApp *domain.OIDCApp
resourceOwner string
}
type res struct {
want *domain.OIDCApp
@@ -280,9 +350,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
{
name: "no aggregate id, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -296,8 +364,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
{
name: "project not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -319,8 +386,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
{
name: "invalid app, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewProjectAddedEvent(context.Background(),
@@ -349,8 +415,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
{
name: "create oidc app basic using whitespaces in uris, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewProjectAddedEvent(context.Background(),
@@ -370,12 +435,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
domain.OIDCVersionV1,
"app1",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
[]string{"https://test.ch"},
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
@@ -418,8 +478,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
AdditionalOrigins: []string{" https://sub.test.ch "},
SkipNativeAppSuccessPage: true,
},
resourceOwner: "org1",
secretGenerator: GetMockSecretGenerator(t),
resourceOwner: "org1",
},
res: res{
want: &domain.OIDCApp{
@@ -430,7 +489,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
AppID: "app1",
AppName: "app",
ClientID: "client1@project",
ClientSecretString: "a",
ClientSecretString: "secret",
AuthMethodType: domain.OIDCAuthMethodTypePost,
OIDCVersion: domain.OIDCVersionV1,
RedirectUris: []string{"https://test.ch"},
@@ -454,8 +513,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
{
name: "create oidc app basic, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewProjectAddedEvent(context.Background(),
@@ -475,12 +533,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
domain.OIDCVersionV1,
"app1",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
[]string{"https://test.ch"},
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
@@ -523,8 +576,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
AdditionalOrigins: []string{"https://sub.test.ch"},
SkipNativeAppSuccessPage: true,
},
resourceOwner: "org1",
secretGenerator: GetMockSecretGenerator(t),
resourceOwner: "org1",
},
res: res{
want: &domain.OIDCApp{
@@ -535,7 +587,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
AppID: "app1",
AppName: "app",
ClientID: "client1@project",
ClientSecretString: "a",
ClientSecretString: "secret",
AuthMethodType: domain.OIDCAuthMethodTypePost,
OIDCVersion: domain.OIDCVersionV1,
RedirectUris: []string{"https://test.ch"},
@@ -560,10 +612,14 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
idGenerator: tt.fields.idGenerator,
eventstore: tt.fields.eventstore(t),
idGenerator: tt.fields.idGenerator,
newHashedSecret: mockHashedSecret("secret"),
defaultSecretGenerators: &SecretGenerators{
ClientSecret: emptyConfig,
},
}
got, err := r.AddOIDCApplication(tt.args.ctx, tt.args.oidcApp, tt.args.resourceOwner, tt.args.secretGenerator)
got, err := r.AddOIDCApplication(tt.args.ctx, tt.args.oidcApp, tt.args.resourceOwner)
if tt.res.err == nil {
assert.NoError(t, err)
}
@@ -709,12 +765,7 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
domain.OIDCVersionV1,
"app1",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
[]string{"https://test.ch"},
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
@@ -783,12 +834,7 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
domain.OIDCVersionV1,
"app1",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
[]string{"https://test.ch"},
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
@@ -857,12 +903,7 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
domain.OIDCVersionV1,
"app1",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
[]string{"https://test.ch"},
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
@@ -965,14 +1006,13 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(*testing.T) *eventstore.Eventstore
}
type args struct {
ctx context.Context
appID string
projectID string
resourceOwner string
secretGenerator crypto.Generator
ctx context.Context
appID string
projectID string
resourceOwner string
}
type res struct {
want *domain.OIDCApp
@@ -987,9 +1027,7 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
{
name: "no projectid, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -1003,9 +1041,7 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
{
name: "no appid, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -1020,8 +1056,7 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
{
name: "app not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -1038,8 +1073,7 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
{
name: "change secret, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(),
@@ -1054,12 +1088,7 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
domain.OIDCVersionV1,
"app1",
"client1@project",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
[]string{"https://test.ch"},
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
@@ -1081,22 +1110,16 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
project.NewOIDCConfigSecretChangedEvent(context.Background(),
&project.NewAggregate("project1", "org1").Aggregate,
"app1",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
),
),
),
},
args: args{
ctx: context.Background(),
projectID: "project1",
appID: "app1",
resourceOwner: "org1",
secretGenerator: GetMockSecretGenerator(t),
ctx: context.Background(),
projectID: "project1",
appID: "app1",
resourceOwner: "org1",
},
res: res{
want: &domain.OIDCApp{
@@ -1107,7 +1130,7 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
AppID: "app1",
AppName: "app",
ClientID: "client1@project",
ClientSecretString: "a",
ClientSecretString: "secret",
AuthMethodType: domain.OIDCAuthMethodTypePost,
OIDCVersion: domain.OIDCVersionV1,
RedirectUris: []string{"https://test.ch"},
@@ -1129,11 +1152,15 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(*testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
newHashedSecret: mockHashedSecret("secret"),
defaultSecretGenerators: &SecretGenerators{
ClientSecret: emptyConfig,
},
}
got, err := r.ChangeOIDCApplicationSecret(tt.args.ctx, tt.args.projectID, tt.args.appID, tt.args.resourceOwner, tt.args.secretGenerator)
got, err := r.ChangeOIDCApplicationSecret(tt.args.ctx, tt.args.projectID, tt.args.appID, tt.args.resourceOwner)
if tt.res.err == nil {
assert.NoError(t, err)
}
@@ -1165,3 +1192,165 @@ func newOIDCAppChangedEvent(ctx context.Context, appID, projectID, resourceOwner
)
return event
}
func TestCommands_VerifyOIDCClientSecret(t *testing.T) {
hasher := &crypto.Hasher{
Swapper: passwap.NewSwapper(bcrypt.New(bcrypt.MinCost)),
}
hashedSecret, err := hasher.Hash("secret")
require.NoError(t, err)
agg := project.NewAggregate("projectID", "orgID")
tests := []struct {
name string
secret string
eventstore func(*testing.T) *eventstore.Eventstore
wantErr error
}{
{
name: "filter error",
eventstore: expectEventstore(
expectFilterError(io.ErrClosedPipe),
),
wantErr: io.ErrClosedPipe,
},
{
name: "app not exists",
eventstore: expectEventstore(
expectFilter(),
),
wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-D8hba", "Errors.Project.App.NotExisting"),
},
{
name: "wrong app type",
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
),
),
),
wantErr: zerrors.ThrowInvalidArgument(nil, "COMMAND-BHgn2", "Errors.Project.App.IsNotOIDC"),
},
{
name: "no secret set",
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
),
eventFromEventPusher(
project.NewOIDCConfigAddedEvent(context.Background(),
&agg.Aggregate,
domain.OIDCVersionV1,
"appID",
"client1@project",
"",
[]string{"https://test.ch"},
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
domain.OIDCApplicationTypeWeb,
domain.OIDCAuthMethodTypePost,
[]string{"https://test.ch/logout"},
true,
domain.OIDCTokenTypeBearer,
true,
true,
true,
time.Second*1,
[]string{"https://sub.test.ch"},
false,
),
),
),
),
wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-D6hba", "Errors.Project.App.OIDCConfigInvalid"),
},
{
name: "check succeeded",
secret: "secret",
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
),
eventFromEventPusher(
project.NewOIDCConfigAddedEvent(context.Background(),
&agg.Aggregate,
domain.OIDCVersionV1,
"appID",
"client1@project",
hashedSecret,
[]string{"https://test.ch"},
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
domain.OIDCApplicationTypeWeb,
domain.OIDCAuthMethodTypePost,
[]string{"https://test.ch/logout"},
true,
domain.OIDCTokenTypeBearer,
true,
true,
true,
time.Second*1,
[]string{"https://sub.test.ch"},
false,
),
),
),
expectPush(
project.NewOIDCConfigSecretCheckSucceededEvent(context.Background(), &agg.Aggregate, "appID"),
),
),
},
{
name: "check failed",
secret: "wrong!",
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
project.NewApplicationAddedEvent(context.Background(), &agg.Aggregate, "appID", "appName"),
),
eventFromEventPusher(
project.NewOIDCConfigAddedEvent(context.Background(),
&agg.Aggregate,
domain.OIDCVersionV1,
"appID",
"client1@project",
hashedSecret,
[]string{"https://test.ch"},
[]domain.OIDCResponseType{domain.OIDCResponseTypeCode},
[]domain.OIDCGrantType{domain.OIDCGrantTypeAuthorizationCode},
domain.OIDCApplicationTypeWeb,
domain.OIDCAuthMethodTypePost,
[]string{"https://test.ch/logout"},
true,
domain.OIDCTokenTypeBearer,
true,
true,
true,
time.Second*1,
[]string{"https://sub.test.ch"},
false,
),
),
),
expectPush(
project.NewOIDCConfigSecretCheckFailedEvent(context.Background(), &agg.Aggregate, "appID"),
),
),
wantErr: zerrors.ThrowInvalidArgument(err, "COMMAND-Bz542", "Errors.Project.App.ClientSecretInvalid"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Commands{
eventstore: tt.eventstore(t),
secretHasher: hasher,
}
err := c.VerifyOIDCClientSecret(context.Background(), "projectID", "appID", tt.secret)
c.jobs.Wait()
require.ErrorIs(t, err, tt.wantErr)
})
}
}
+3 -3
View File
@@ -31,11 +31,11 @@ type SessionCommands struct {
eventstore *eventstore.Eventstore
eventCommands []eventstore.Command
hasher *crypto.PasswordHasher
hasher *crypto.Hasher
intentAlg crypto.EncryptionAlgorithm
totpAlg crypto.EncryptionAlgorithm
otpAlg crypto.EncryptionAlgorithm
createCode cryptoCodeWithDefaultFunc
createCode encryptedCodeWithDefaultFunc
createToken func(sessionID string) (id string, token string, err error)
now func() time.Time
}
@@ -49,7 +49,7 @@ func (c *Commands) NewSessionCommands(cmds []SessionCommand, session *SessionWri
intentAlg: c.idpConfigEncryption,
totpAlg: c.multifactors.OTP.CryptoMFA,
otpAlg: c.userEncryption,
createCode: c.newCodeWithDefault,
createCode: c.newEncryptedCodeWithDefault,
createToken: c.sessionTokenCreator,
now: time.Now,
}
+2 -2
View File
@@ -120,7 +120,7 @@ func CheckOTPSMS(code string) SessionCommand {
if challenge == nil {
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-SF3tv", "Errors.User.Code.NotFound")
}
err = crypto.VerifyCodeWithAlgorithm(challenge.CreationDate, challenge.Expiry, challenge.Code, code, cmd.otpAlg)
err = crypto.VerifyCode(challenge.CreationDate, challenge.Expiry, challenge.Code, code, cmd.otpAlg)
if err != nil {
return err
}
@@ -138,7 +138,7 @@ func CheckOTPEmail(code string) SessionCommand {
if challenge == nil {
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-zF3g3", "Errors.User.Code.NotFound")
}
err = crypto.VerifyCodeWithAlgorithm(challenge.CreationDate, challenge.Expiry, challenge.Code, code, cmd.otpAlg)
err = crypto.VerifyCode(challenge.CreationDate, challenge.Expiry, challenge.Code, code, cmd.otpAlg)
if err != nil {
return err
}
+10 -10
View File
@@ -20,7 +20,7 @@ func TestCommands_CreateOTPSMSChallengeReturnCode(t *testing.T) {
type fields struct {
userID string
eventstore func(*testing.T) *eventstore.Eventstore
createCode cryptoCodeWithDefaultFunc
createCode encryptedCodeWithDefaultFunc
}
type res struct {
err error
@@ -65,7 +65,7 @@ func TestCommands_CreateOTPSMSChallengeReturnCode(t *testing.T) {
),
),
),
createCode: mockCodeWithDefault("1234567", 5*time.Minute),
createCode: mockEncryptedCodeWithDefault("1234567", 5*time.Minute),
},
res: res{
returnCode: "1234567",
@@ -122,7 +122,7 @@ func TestCommands_CreateOTPSMSChallenge(t *testing.T) {
type fields struct {
userID string
eventstore func(*testing.T) *eventstore.Eventstore
createCode cryptoCodeWithDefaultFunc
createCode encryptedCodeWithDefaultFunc
}
type res struct {
err error
@@ -166,7 +166,7 @@ func TestCommands_CreateOTPSMSChallenge(t *testing.T) {
),
),
),
createCode: mockCodeWithDefault("1234567", 5*time.Minute),
createCode: mockEncryptedCodeWithDefault("1234567", 5*time.Minute),
},
res: res{
commands: []eventstore.Command{
@@ -292,7 +292,7 @@ func TestCommands_CreateOTPEmailChallengeURLTemplate(t *testing.T) {
type fields struct {
userID string
eventstore func(*testing.T) *eventstore.Eventstore
createCode cryptoCodeWithDefaultFunc
createCode encryptedCodeWithDefaultFunc
}
type args struct {
urlTmpl string
@@ -361,7 +361,7 @@ func TestCommands_CreateOTPEmailChallengeURLTemplate(t *testing.T) {
),
),
),
createCode: mockCodeWithDefault("1234567", 5*time.Minute),
createCode: mockEncryptedCodeWithDefault("1234567", 5*time.Minute),
},
res: res{
commands: []eventstore.Command{
@@ -421,7 +421,7 @@ func TestCommands_CreateOTPEmailChallengeReturnCode(t *testing.T) {
type fields struct {
userID string
eventstore func(*testing.T) *eventstore.Eventstore
createCode cryptoCodeWithDefaultFunc
createCode encryptedCodeWithDefaultFunc
}
type res struct {
err error
@@ -465,7 +465,7 @@ func TestCommands_CreateOTPEmailChallengeReturnCode(t *testing.T) {
),
),
),
createCode: mockCodeWithDefault("1234567", 5*time.Minute),
createCode: mockEncryptedCodeWithDefault("1234567", 5*time.Minute),
},
res: res{
returnCode: "1234567",
@@ -523,7 +523,7 @@ func TestCommands_CreateOTPEmailChallenge(t *testing.T) {
type fields struct {
userID string
eventstore func(*testing.T) *eventstore.Eventstore
createCode cryptoCodeWithDefaultFunc
createCode encryptedCodeWithDefaultFunc
}
type res struct {
err error
@@ -566,7 +566,7 @@ func TestCommands_CreateOTPEmailChallenge(t *testing.T) {
),
),
),
createCode: mockCodeWithDefault("1234567", 5*time.Minute),
createCode: mockEncryptedCodeWithDefault("1234567", 5*time.Minute),
},
res: res{
commands: []eventstore.Command{
+2 -2
View File
@@ -476,8 +476,8 @@ func ExistsUser(ctx context.Context, filter preparation.FilterToQueryReducer, id
return exists, nil
}
func (c *Commands) newUserInitCode(ctx context.Context, filter preparation.FilterToQueryReducer, alg crypto.EncryptionAlgorithm) (*CryptoCode, error) {
return c.newCode(ctx, filter, domain.SecretGeneratorTypeInitCode, alg)
func (c *Commands) newUserInitCode(ctx context.Context, filter preparation.FilterToQueryReducer, alg crypto.EncryptionAlgorithm) (*EncryptedCode, error) {
return c.newEncryptedCode(ctx, filter, domain.SecretGeneratorTypeInitCode, alg)
}
func userWriteModelByID(ctx context.Context, filter preparation.FilterToQueryReducer, userID, resourceOwner string) (*UserWriteModel, error) {
+9 -6
View File
@@ -12,6 +12,7 @@ import (
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
"github.com/zitadel/zitadel/internal/repository/user"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
"github.com/zitadel/zitadel/internal/zerrors"
)
@@ -77,7 +78,7 @@ type AddLink struct {
IDPExternalID string
}
func (h *AddHuman) Validate(hasher *crypto.PasswordHasher) (err error) {
func (h *AddHuman) Validate(hasher *crypto.Hasher) (err error) {
if err := h.Email.Validate(); err != nil {
return err
}
@@ -164,7 +165,7 @@ type humanCreationCommand interface {
}
//nolint:gocognit
func (c *Commands) AddHumanCommand(human *AddHuman, orgID string, hasher *crypto.PasswordHasher, codeAlg crypto.EncryptionAlgorithm, allowInitMail bool) preparation.Validation {
func (c *Commands) AddHumanCommand(human *AddHuman, orgID string, hasher *crypto.Hasher, codeAlg crypto.EncryptionAlgorithm, allowInitMail bool) preparation.Validation {
return func() (_ preparation.CreateCommands, err error) {
if err := human.Validate(hasher); err != nil {
return nil, err
@@ -329,17 +330,19 @@ func (c *Commands) addHumanCommandCheckID(ctx context.Context, filter preparatio
return nil
}
func addHumanCommandPassword(ctx context.Context, filter preparation.FilterToQueryReducer, createCmd humanCreationCommand, human *AddHuman, hasher *crypto.PasswordHasher) (err error) {
func addHumanCommandPassword(ctx context.Context, filter preparation.FilterToQueryReducer, createCmd humanCreationCommand, human *AddHuman, hasher *crypto.Hasher) (err error) {
if human.Password != "" {
if err = humanValidatePassword(ctx, filter, human.Password); err != nil {
return err
}
secret, err := hasher.Hash(human.Password)
_, spanHash := tracing.NewNamedSpan(ctx, "passwap.Hash")
encodedHash, err := hasher.Hash(human.Password)
spanHash.EndWithError(err)
if err != nil {
return err
}
createCmd.AddPasswordData(secret, human.PasswordChangeRequired)
createCmd.AddPasswordData(encodedHash, human.PasswordChangeRequired)
return nil
}
@@ -589,7 +592,7 @@ func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.
human.EnsureDisplayName()
if human.Password != nil {
if err := human.HashPasswordIfExisting(pwPolicy, c.userPasswordHasher, human.Password.ChangeRequired); err != nil {
if err := human.HashPasswordIfExisting(ctx, pwPolicy, c.userPasswordHasher, human.Password.ChangeRequired); err != nil {
return nil, nil, err
}
}
+1 -1
View File
@@ -81,7 +81,7 @@ func (c *Commands) VerifyHumanEmail(ctx context.Context, userID, code, resourceo
}
userAgg := UserAggregateFromWriteModel(&existingCode.WriteModel)
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, emailCodeGenerator)
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, emailCodeGenerator.Alg())
if err == nil {
pushedEvents, err := c.eventstore.Push(ctx, user.NewHumanEmailVerifiedEvent(ctx, userAgg))
if err != nil {
+1 -1
View File
@@ -67,7 +67,7 @@ func (c *Commands) HumanVerifyInitCode(ctx context.Context, userID, resourceOwne
}
userAgg := UserAggregateFromWriteModel(&existingCode.WriteModel)
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, initCodeGenerator)
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, initCodeGenerator.Alg())
if err != nil {
_, err = c.eventstore.Push(ctx, user.NewHumanInitializedCheckFailedEvent(ctx, userAgg))
logging.WithFields("userID", userAgg.ID).OnError(err).Error("NewHumanInitializedCheckFailedEvent push failed")
+1 -1
View File
@@ -292,7 +292,7 @@ func TestCommandSide_ResendInitialMail(t *testing.T) {
func TestCommandSide_VerifyInitCode(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
userPasswordHasher *crypto.PasswordHasher
userPasswordHasher *crypto.Hasher
}
type args struct {
ctx context.Context
+2 -2
View File
@@ -455,7 +455,7 @@ func (c *Commands) sendHumanOTP(
if !existingOTP.OTPAdded() {
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-SFD52", "Errors.User.MFA.OTP.NotReady")
}
config, err := secretGeneratorConfigWithDefault(ctx, c.eventstore.Filter, secretGeneratorType, defaultSecretGenerator)
config, err := cryptoGeneratorConfigWithDefault(ctx, c.eventstore.Filter, secretGeneratorType, defaultSecretGenerator) //nolint:staticcheck
if err != nil {
return err
}
@@ -515,7 +515,7 @@ func (c *Commands) humanCheckOTP(
return zerrors.ThrowPreconditionFailed(nil, "COMMAND-S34gh", "Errors.User.Code.NotFound")
}
userAgg := &user.NewAggregate(userID, existingOTP.ResourceOwner()).Aggregate
err = crypto.VerifyCodeWithAlgorithm(existingOTP.CodeCreationDate(), existingOTP.CodeExpiry(), existingOTP.Code(), code, c.userEncryption)
err = crypto.VerifyCode(existingOTP.CodeCreationDate(), existingOTP.CodeExpiry(), existingOTP.Code(), code, c.userEncryption)
if err == nil {
_, err = c.eventstore.Push(ctx, checkSucceededEvent(ctx, userAgg, authRequestDomainToAuthRequestInfo(authRequest)))
return err
+1 -1
View File
@@ -53,7 +53,7 @@ func (c *Commands) SetPasswordWithVerifyCode(ctx context.Context, orgID, userID,
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.Code.NotFound")
}
err = crypto.VerifyCodeWithAlgorithm(wm.CodeCreationDate, wm.CodeExpiry, wm.Code, code, c.userEncryption)
err = crypto.VerifyCode(wm.CodeCreationDate, wm.CodeExpiry, wm.Code, code, c.userEncryption)
if err != nil {
return nil, err
}
@@ -36,11 +36,11 @@ func (wm *HumanPasswordWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *user.HumanAddedEvent:
wm.EncodedHash = user.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.EncodedHash = crypto.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.SecretChangeRequired = e.ChangeRequired
wm.UserState = domain.UserStateActive
case *user.HumanRegisteredEvent:
wm.EncodedHash = user.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.EncodedHash = crypto.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.SecretChangeRequired = e.ChangeRequired
wm.UserState = domain.UserStateActive
case *user.HumanInitialCodeAddedEvent:
@@ -48,7 +48,7 @@ func (wm *HumanPasswordWriteModel) Reduce() error {
case *user.HumanInitializedCheckSucceededEvent:
wm.UserState = domain.UserStateActive
case *user.HumanPasswordChangedEvent:
wm.EncodedHash = user.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.EncodedHash = crypto.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.SecretChangeRequired = e.ChangeRequired
wm.Code = nil
wm.PasswordCheckFailedCount = 0
+4 -4
View File
@@ -23,7 +23,7 @@ import (
func TestCommandSide_SetOneTimePassword(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
userPasswordHasher *crypto.PasswordHasher
userPasswordHasher *crypto.Hasher
checkPermission domain.PermissionCheck
}
type args struct {
@@ -270,7 +270,7 @@ func TestCommandSide_SetPasswordWithVerifyCode(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
userEncryption crypto.EncryptionAlgorithm
userPasswordHasher *crypto.PasswordHasher
userPasswordHasher *crypto.Hasher
}
type args struct {
ctx context.Context
@@ -598,7 +598,7 @@ func TestCommandSide_SetPasswordWithVerifyCode(t *testing.T) {
func TestCommandSide_ChangePassword(t *testing.T) {
type fields struct {
userPasswordHasher *crypto.PasswordHasher
userPasswordHasher *crypto.Hasher
}
type args struct {
ctx context.Context
@@ -1202,7 +1202,7 @@ func TestCommandSide_PasswordCodeSent(t *testing.T) {
func TestCommandSide_CheckPassword(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
userPasswordHasher *crypto.PasswordHasher
userPasswordHasher *crypto.Hasher
}
type args struct {
ctx context.Context
+2 -2
View File
@@ -79,7 +79,7 @@ func (c *Commands) VerifyHumanPhone(ctx context.Context, userID, code, resourceo
}
userAgg := UserAggregateFromWriteModel(&existingCode.WriteModel)
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, phoneCodeGenerator)
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, phoneCodeGenerator.Alg())
if err == nil {
pushedEvents, err := c.eventstore.Push(ctx, user.NewHumanPhoneVerifiedEvent(ctx, userAgg))
if err != nil {
@@ -115,7 +115,7 @@ func (c *Commands) CreateHumanPhoneVerificationCode(ctx context.Context, userID,
if existingPhone.IsPhoneVerified {
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-2M9sf", "Errors.User.Phone.AlreadyVerified")
}
config, err := secretGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyPhoneCode)
config, err := cryptoGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyPhoneCode) //nolint:staticcheck
if err != nil {
return nil, err
}
+16 -16
View File
@@ -28,9 +28,9 @@ func TestCommandSide_AddHuman(t *testing.T) {
type fields struct {
eventstore func(t *testing.T) *eventstore.Eventstore
idGenerator id.Generator
userPasswordHasher *crypto.PasswordHasher
userPasswordHasher *crypto.Hasher
codeAlg crypto.EncryptionAlgorithm
newCode cryptoCodeFunc
newCode encrypedCodeFunc
}
type args struct {
ctx context.Context
@@ -245,7 +245,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -312,7 +312,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -380,7 +380,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -450,7 +450,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
userPasswordHasher: mockPasswordHasher("x"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -521,7 +521,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
userPasswordHasher: mockPasswordHasher("x"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
newCode: mockCode("emailCode", time.Hour),
newCode: mockEncryptedCode("emailCode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -593,7 +593,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
userPasswordHasher: mockPasswordHasher("x"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
newCode: mockCode("emailCode", time.Hour),
newCode: mockEncryptedCode("emailCode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -996,7 +996,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
userPasswordHasher: mockPasswordHasher("x"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
newCode: mockCode("phonecode", time.Hour),
newCode: mockEncryptedCode("phonecode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -1061,7 +1061,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -1136,7 +1136,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
userPasswordHasher: mockPasswordHasher("x"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
newCode: mockCode("phoneCode", time.Hour),
newCode: mockEncryptedCode("phoneCode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -1204,7 +1204,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -1242,7 +1242,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
userPasswordHasher: tt.fields.userPasswordHasher,
userEncryption: tt.fields.codeAlg,
idGenerator: tt.fields.idGenerator,
newCode: tt.fields.newCode,
newEncryptedCode: tt.fields.newCode,
}
err := r.AddHuman(tt.args.ctx, tt.args.orgID, tt.args.human, tt.args.allowInitMail)
if tt.res.err == nil {
@@ -1266,7 +1266,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
idGenerator id.Generator
userPasswordHasher *crypto.PasswordHasher
userPasswordHasher *crypto.Hasher
}
type args struct {
ctx context.Context
@@ -2483,7 +2483,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
idGenerator id.Generator
userPasswordHasher *crypto.PasswordHasher
userPasswordHasher *crypto.Hasher
}
type args struct {
ctx context.Context
@@ -4328,7 +4328,7 @@ func TestAddHumanCommand(t *testing.T) {
type args struct {
human *AddHuman
orgID string
hasher *crypto.PasswordHasher
hasher *crypto.Hasher
filter preparation.FilterToQueryReducer
codeAlg crypto.EncryptionAlgorithm
allowInitMail bool
+1 -1
View File
@@ -575,7 +575,7 @@ func (c *Commands) humanVerifyPasswordlessInitCode(ctx context.Context, userID,
if err != nil {
return err
}
err = crypto.VerifyCode(initCode.ChangeDate, initCode.Expiration, initCode.CryptoCode, verificationCode, passwordlessCodeGenerator)
err = crypto.VerifyCode(initCode.ChangeDate, initCode.Expiration, initCode.CryptoCode, verificationCode, passwordlessCodeGenerator.Alg())
if err != nil || initCode.State != domain.PasswordlessInitCodeStateActive {
userAgg := UserAggregateFromWriteModel(&initCode.WriteModel)
_, err = c.eventstore.Push(ctx, usr_repo.NewHumanPasswordlessInitCodeCheckFailedEvent(ctx, userAgg, codeID))
+8 -6
View File
@@ -18,8 +18,7 @@ type MachineWriteModel struct {
Description string
UserState domain.UserState
AccessTokenType domain.OIDCTokenType
ClientSecret *crypto.CryptoValue
HashedSecret string
}
func NewMachineWriteModel(userID, resourceOwner string) *MachineWriteModel {
@@ -71,9 +70,11 @@ func (wm *MachineWriteModel) Reduce() error {
case *user.UserRemovedEvent:
wm.UserState = domain.UserStateDeleted
case *user.MachineSecretSetEvent:
wm.ClientSecret = e.ClientSecret
wm.HashedSecret = crypto.SecretOrEncodedHash(e.ClientSecret, e.HashedSecret)
case *user.MachineSecretRemovedEvent:
wm.ClientSecret = nil
wm.HashedSecret = ""
case *user.MachineSecretHashUpdatedEvent:
wm.HashedSecret = e.HashedSecret
}
}
return wm.WriteModel.Reduce()
@@ -94,8 +95,9 @@ func (wm *MachineWriteModel) Query() *eventstore.SearchQueryBuilder {
user.UserReactivatedType,
user.UserRemovedType,
user.MachineSecretSetType,
user.MachineSecretRemovedType).
Builder()
user.MachineSecretRemovedType,
user.MachineSecretHashUpdatedType,
).Builder()
}
func (wm *MachineWriteModel) NewChangedEvent(
+16 -11
View File
@@ -4,7 +4,6 @@ import (
"context"
"github.com/zitadel/zitadel/internal/command/preparation"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/user"
@@ -15,9 +14,9 @@ type GenerateMachineSecret struct {
ClientSecret string
}
func (c *Commands) GenerateMachineSecret(ctx context.Context, userID string, resourceOwner string, generator crypto.Generator, set *GenerateMachineSecret) (*domain.ObjectDetails, error) {
func (c *Commands) GenerateMachineSecret(ctx context.Context, userID string, resourceOwner string, set *GenerateMachineSecret) (*domain.ObjectDetails, error) {
agg := user.NewAggregate(userID, resourceOwner)
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, prepareGenerateMachineSecret(agg, generator, set))
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareGenerateMachineSecret(agg, set)) //nolint:staticcheck
if err != nil {
return nil, err
}
@@ -34,7 +33,7 @@ func (c *Commands) GenerateMachineSecret(ctx context.Context, userID string, res
}, nil
}
func prepareGenerateMachineSecret(a *user.Aggregate, generator crypto.Generator, set *GenerateMachineSecret) preparation.Validation {
func (c *Commands) prepareGenerateMachineSecret(a *user.Aggregate, set *GenerateMachineSecret) preparation.Validation {
return func() (_ preparation.CreateCommands, err error) {
if a.ResourceOwner == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-x0992n", "Errors.ResourceOwnerMissing")
@@ -50,15 +49,14 @@ func prepareGenerateMachineSecret(a *user.Aggregate, generator crypto.Generator,
if !isUserStateExists(writeModel.UserState) {
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-x8910n", "Errors.User.NotExisting")
}
clientSecret, secretString, err := domain.NewMachineClientSecret(generator)
encodedHash, plain, err := c.newHashedSecret(ctx, filter)
if err != nil {
return nil, err
}
set.ClientSecret = secretString
set.ClientSecret = plain
return []eventstore.Command{
user.NewMachineSecretSetEvent(ctx, &a.Aggregate, clientSecret),
user.NewMachineSecretSetEvent(ctx, &a.Aggregate, encodedHash),
}, nil
}, nil
}
@@ -99,7 +97,7 @@ func prepareRemoveMachineSecret(a *user.Aggregate) preparation.Validation {
if !isUserStateExists(writeModel.UserState) {
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-x7s802", "Errors.User.NotExisting")
}
if writeModel.ClientSecret == nil {
if writeModel.HashedSecret == "" {
return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-coi82n", "Errors.User.Machine.Secret.NotExisting")
}
return []eventstore.Command{
@@ -109,9 +107,16 @@ func prepareRemoveMachineSecret(a *user.Aggregate) preparation.Validation {
}
}
func (c *Commands) MachineSecretCheckSucceeded(ctx context.Context, userID, resourceOwner string) {
func (c *Commands) MachineSecretCheckSucceeded(ctx context.Context, userID, resourceOwner, updated string) {
agg := user.NewAggregate(userID, resourceOwner)
c.asyncPush(ctx, user.NewMachineSecretCheckSucceededEvent(ctx, &agg.Aggregate))
cmds := append(
make([]eventstore.Command, 0, 2),
user.NewMachineSecretCheckSucceededEvent(ctx, &agg.Aggregate),
)
if updated != "" {
cmds = append(cmds, user.NewMachineSecretHashUpdatedEvent(ctx, &agg.Aggregate, updated))
}
c.asyncPush(ctx, cmds...)
}
func (c *Commands) MachineSecretCheckFailed(ctx context.Context, userID, resourceOwner string) {
+15 -33
View File
@@ -8,7 +8,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/user"
@@ -17,13 +16,12 @@ import (
func TestCommandSide_GenerateMachineSecret(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(*testing.T) *eventstore.Eventstore
}
type args struct {
ctx context.Context
userID string
resourceOwner string
generator crypto.Generator
set *GenerateMachineSecret
}
type res struct {
@@ -40,15 +38,12 @@ func TestCommandSide_GenerateMachineSecret(t *testing.T) {
{
name: "user invalid, invalid argument error userID",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
userID: "",
resourceOwner: "org1",
generator: GetMockSecretGenerator(t),
set: nil,
},
res: res{
@@ -58,15 +53,12 @@ func TestCommandSide_GenerateMachineSecret(t *testing.T) {
{
name: "user invalid, invalid argument error resourceowner",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "",
generator: GetMockSecretGenerator(t),
set: nil,
},
res: res{
@@ -76,8 +68,7 @@ func TestCommandSide_GenerateMachineSecret(t *testing.T) {
{
name: "user not existing, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -85,7 +76,6 @@ func TestCommandSide_GenerateMachineSecret(t *testing.T) {
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
generator: GetMockSecretGenerator(t),
set: nil,
},
res: res{
@@ -95,8 +85,7 @@ func TestCommandSide_GenerateMachineSecret(t *testing.T) {
{
name: "add machine secret, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
@@ -112,12 +101,7 @@ func TestCommandSide_GenerateMachineSecret(t *testing.T) {
expectPush(
user.NewMachineSecretSetEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
),
),
),
@@ -126,7 +110,6 @@ func TestCommandSide_GenerateMachineSecret(t *testing.T) {
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
generator: GetMockSecretGenerator(t),
set: &GenerateMachineSecret{},
},
res: res{
@@ -134,7 +117,7 @@ func TestCommandSide_GenerateMachineSecret(t *testing.T) {
ResourceOwner: "org1",
},
secret: &GenerateMachineSecret{
ClientSecret: "a",
ClientSecret: "secret",
},
},
},
@@ -142,9 +125,13 @@ func TestCommandSide_GenerateMachineSecret(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
newHashedSecret: mockHashedSecret("secret"),
defaultSecretGenerators: &SecretGenerators{
ClientSecret: emptyConfig,
},
}
got, err := r.GenerateMachineSecret(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.generator, tt.args.set)
got, err := r.GenerateMachineSecret(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.set)
if tt.res.err == nil {
assert.NoError(t, err)
}
@@ -274,12 +261,7 @@ func TestCommandSide_RemoveMachineSecret(t *testing.T) {
eventFromEventPusher(
user.NewMachineSecretSetEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
"secret",
),
),
),
@@ -333,7 +315,7 @@ func TestCommands_MachineSecretCheckSucceeded(t *testing.T) {
expectPushSlow(time.Second/100, cmd),
),
}
c.MachineSecretCheckSucceeded(ctx, "userID", "orgID")
c.MachineSecretCheckSucceeded(ctx, "userID", "orgID", "")
require.NoError(t, c.Close(ctx))
}
+4 -4
View File
@@ -76,7 +76,7 @@ func (c *Commands) ChangeUserEmailVerified(ctx context.Context, userID, email st
}
func (c *Commands) changeUserEmailWithCode(ctx context.Context, userID, email string, alg crypto.EncryptionAlgorithm, returnCode bool, urlTmpl string) (*domain.Email, error) {
config, err := secretGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyEmailCode)
config, err := cryptoGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyEmailCode) //nolint:staticcheck
if err != nil {
return nil, err
}
@@ -85,7 +85,7 @@ func (c *Commands) changeUserEmailWithCode(ctx context.Context, userID, email st
}
func (c *Commands) resendUserEmailCode(ctx context.Context, userID string, alg crypto.EncryptionAlgorithm, returnCode bool, urlTmpl string) (*domain.Email, error) {
config, err := secretGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyEmailCode) //nolint:staticcheck
config, err := cryptoGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyEmailCode) //nolint:staticcheck
if err != nil {
return nil, err
}
@@ -152,7 +152,7 @@ func (c *Commands) resendUserEmailCodeWithGeneratorEvents(ctx context.Context, u
}
func (c *Commands) VerifyUserEmail(ctx context.Context, userID, code string, alg crypto.EncryptionAlgorithm) (*domain.ObjectDetails, error) {
config, err := secretGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyEmailCode)
config, err := cryptoGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyEmailCode) //nolint:staticcheck
if err != nil {
return nil, err
}
@@ -262,7 +262,7 @@ func (c *UserEmailEvents) VerifyCode(ctx context.Context, code string, gen crypt
return zerrors.ThrowInvalidArgument(nil, "COMMAND-Fia4a", "Errors.User.Code.Empty")
}
err := crypto.VerifyCode(c.model.CodeCreationDate, c.model.CodeExpiry, c.model.Code, code, gen)
err := crypto.VerifyCode(c.model.CodeCreationDate, c.model.CodeExpiry, c.model.Code, code, gen.Alg())
if err == nil {
c.events = append(c.events, user.NewHumanEmailVerifiedEvent(ctx, c.aggregate))
return nil
+3 -3
View File
@@ -51,7 +51,7 @@ type Password struct {
ChangeRequired bool
}
func (h *ChangeHuman) Validate(hasher *crypto.PasswordHasher) (err error) {
func (h *ChangeHuman) Validate(hasher *crypto.Hasher) (err error) {
if h.Email != nil && h.Email.Address != "" {
if err := h.Email.Validate(); err != nil {
return err
@@ -72,7 +72,7 @@ func (h *ChangeHuman) Validate(hasher *crypto.PasswordHasher) (err error) {
return nil
}
func (p *Password) Validate(hasher *crypto.PasswordHasher) error {
func (p *Password) Validate(hasher *crypto.Hasher) error {
if p.EncodedPasswordHash != nil {
if !hasher.EncodingSupported(*p.EncodedPasswordHash) {
return zerrors.ThrowInvalidArgument(nil, "USER-oz74onzvqr", "Errors.User.Password.NotSupported")
@@ -373,7 +373,7 @@ func (c *Commands) changeUserPassword(ctx context.Context, cmds []eventstore.Com
// Either have a code to set the password
if password.PasswordCode != nil {
if err := crypto.VerifyCodeWithAlgorithm(wm.PasswordCodeCreationDate, wm.PasswordCodeExpiry, wm.PasswordCode, *password.PasswordCode, alg); err != nil {
if err := crypto.VerifyCode(wm.PasswordCodeCreationDate, wm.PasswordCodeExpiry, wm.PasswordCode, *password.PasswordCode, alg); err != nil {
return cmds, err
}
}
+20 -20
View File
@@ -25,8 +25,8 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
type fields struct {
eventstore func(t *testing.T) *eventstore.Eventstore
idGenerator id.Generator
userPasswordHasher *crypto.PasswordHasher
newCode cryptoCodeFunc
userPasswordHasher *crypto.Hasher
newCode encrypedCodeFunc
checkPermission domain.PermissionCheck
}
type args struct {
@@ -247,7 +247,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -283,7 +283,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
checkPermission: newMockPermissionCheckNotAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -349,7 +349,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -420,7 +420,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
userPasswordHasher: mockPasswordHasher("x"),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -492,7 +492,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
userPasswordHasher: mockPasswordHasher("x"),
newCode: mockCode("emailCode", time.Hour),
newCode: mockEncryptedCode("emailCode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -565,7 +565,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
userPasswordHasher: mockPasswordHasher("x"),
newCode: mockCode("emailCode", time.Hour),
newCode: mockEncryptedCode("emailCode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -974,7 +974,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
userPasswordHasher: mockPasswordHasher("x"),
newCode: mockCode("phonecode", time.Hour),
newCode: mockEncryptedCode("phonecode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -1040,7 +1040,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -1116,7 +1116,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
userPasswordHasher: mockPasswordHasher("x"),
newCode: mockCode("phoneCode", time.Hour),
newCode: mockEncryptedCode("phoneCode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -1185,7 +1185,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
newCode: mockCode("userinit", time.Hour),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -1223,7 +1223,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
eventstore: tt.fields.eventstore(t),
userPasswordHasher: tt.fields.userPasswordHasher,
idGenerator: tt.fields.idGenerator,
newCode: tt.fields.newCode,
newEncryptedCode: tt.fields.newCode,
checkPermission: tt.fields.checkPermission,
}
err := r.AddUserHuman(tt.args.ctx, tt.args.orgID, tt.args.human, tt.args.allowInitMail, tt.args.codeAlg)
@@ -1247,8 +1247,8 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
func TestCommandSide_ChangeUserHuman(t *testing.T) {
type fields struct {
eventstore func(t *testing.T) *eventstore.Eventstore
userPasswordHasher *crypto.PasswordHasher
newCode cryptoCodeFunc
userPasswordHasher *crypto.Hasher
newCode encrypedCodeFunc
checkPermission domain.PermissionCheck
}
type args struct {
@@ -1562,7 +1562,7 @@ func TestCommandSide_ChangeUserHuman(t *testing.T) {
),
),
checkPermission: newMockPermissionCheckAllowed(),
newCode: mockCode("emailCode", time.Hour),
newCode: mockEncryptedCode("emailCode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -1741,7 +1741,7 @@ func TestCommandSide_ChangeUserHuman(t *testing.T) {
),
),
checkPermission: newMockPermissionCheckAllowed(),
newCode: mockCode("emailCode", time.Hour),
newCode: mockEncryptedCode("emailCode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -1791,7 +1791,7 @@ func TestCommandSide_ChangeUserHuman(t *testing.T) {
),
),
checkPermission: newMockPermissionCheckAllowed(),
newCode: mockCode("phoneCode", time.Hour),
newCode: mockEncryptedCode("phoneCode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -1939,7 +1939,7 @@ func TestCommandSide_ChangeUserHuman(t *testing.T) {
),
),
checkPermission: newMockPermissionCheckAllowed(),
newCode: mockCode("phoneCode", time.Hour),
newCode: mockEncryptedCode("phoneCode", time.Hour),
},
args: args{
ctx: context.Background(),
@@ -2546,7 +2546,7 @@ func TestCommandSide_ChangeUserHuman(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
userPasswordHasher: tt.fields.userPasswordHasher,
newCode: tt.fields.newCode,
newEncryptedCode: tt.fields.newCode,
checkPermission: tt.fields.checkPermission,
}
err := r.ChangeUserHuman(tt.args.ctx, tt.args.human, tt.args.codeAlg)
+3 -3
View File
@@ -266,7 +266,7 @@ func (wm *UserV2WriteModel) Reduce() error {
case *user.HumanPasswordCheckSucceededEvent:
wm.PasswordCheckFailedCount = 0
case *user.HumanPasswordChangedEvent:
wm.PasswordEncodedHash = user.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.PasswordEncodedHash = crypto.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.PasswordChangeRequired = e.ChangeRequired
wm.EmptyPasswordCode()
case *user.HumanPasswordCodeAddedEvent:
@@ -470,7 +470,7 @@ func (wm *UserV2WriteModel) reduceHumanAddedEvent(e *user.HumanAddedEvent) {
wm.Email = e.EmailAddress
wm.Phone = e.PhoneNumber
wm.UserState = domain.UserStateActive
wm.PasswordEncodedHash = user.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.PasswordEncodedHash = crypto.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.PasswordChangeRequired = e.ChangeRequired
}
@@ -485,7 +485,7 @@ func (wm *UserV2WriteModel) reduceHumanRegisteredEvent(e *user.HumanRegisteredEv
wm.Email = e.EmailAddress
wm.Phone = e.PhoneNumber
wm.UserState = domain.UserStateActive
wm.PasswordEncodedHash = user.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.PasswordEncodedHash = crypto.SecretOrEncodedHash(e.Secret, e.EncodedHash)
wm.PasswordChangeRequired = e.ChangeRequired
}
+3 -3
View File
@@ -48,7 +48,7 @@ func (c *Commands) verifyUserPasskeyCode(ctx context.Context, userID, resourceOw
if err != nil {
return nil, err
}
err = verifyCryptoCode(ctx, c.eventstore.Filter, domain.SecretGeneratorTypePasswordlessInitCode, alg, wm.ChangeDate, wm.Expiration, wm.CryptoCode, code)
err = verifyEncryptedCode(ctx, c.eventstore.Filter, domain.SecretGeneratorTypePasswordlessInitCode, alg, wm.ChangeDate, wm.Expiration, wm.CryptoCode, code) //nolint:staticcheck
if err != nil || wm.State != domain.PasswordlessInitCodeStateActive {
c.verifyUserPasskeyCodeFailed(ctx, wm)
return nil, zerrors.ThrowInvalidArgument(err, "COMMAND-Eeb2a", "Errors.User.Code.Invalid")
@@ -156,6 +156,6 @@ func (c *Commands) addUserPasskeyCode(ctx context.Context, userID, resourceOwner
}, nil
}
func (c *Commands) newPasskeyCode(ctx context.Context, filter preparation.FilterToQueryReducer, alg crypto.EncryptionAlgorithm) (*CryptoCode, error) {
return c.newCode(ctx, filter, domain.SecretGeneratorTypePasswordlessInitCode, alg)
func (c *Commands) newPasskeyCode(ctx context.Context, filter preparation.FilterToQueryReducer, alg crypto.EncryptionAlgorithm) (*EncryptedCode, error) {
return c.newEncryptedCode(ctx, filter, domain.SecretGeneratorTypePasswordlessInitCode, alg)
}
+30 -30
View File
@@ -138,7 +138,7 @@ func TestCommands_RegisterUserPasskeyWithCode(t *testing.T) {
es := eventstoreExpect(t,
expectFilter(eventFromEventPusher(testSecretGeneratorAddedEvent(domain.SecretGeneratorTypePasswordlessInitCode))),
)
code, err := newCryptoCode(ctx, es.Filter, domain.SecretGeneratorTypePasswordlessInitCode, alg)
code, err := newEncryptedCode(ctx, es.Filter, domain.SecretGeneratorTypePasswordlessInitCode, alg) //nolint:staticcheck
require.NoError(t, err)
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
@@ -236,7 +236,7 @@ func TestCommands_verifyUserPasskeyCode(t *testing.T) {
es := eventstoreExpect(t,
expectFilter(eventFromEventPusher(testSecretGeneratorAddedEvent(domain.SecretGeneratorTypePasswordlessInitCode))),
)
code, err := newCryptoCode(ctx, es.Filter, domain.SecretGeneratorTypePasswordlessInitCode, alg)
code, err := newEncryptedCode(ctx, es.Filter, domain.SecretGeneratorTypePasswordlessInitCode, alg) //nolint:staticcheck
require.NoError(t, err)
userAgg := &user.NewAggregate("user1", "org1").Aggregate
@@ -457,7 +457,7 @@ func TestCommands_AddUserPasskeyCode(t *testing.T) {
alg := crypto.CreateMockEncryptionAlg(gomock.NewController(t))
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
newCode cryptoCodeFunc
newCode encrypedCodeFunc
eventstore func(t *testing.T) *eventstore.Eventstore
idGenerator id.Generator
}
@@ -475,7 +475,7 @@ func TestCommands_AddUserPasskeyCode(t *testing.T) {
{
name: "id generator error",
fields: fields{
newCode: mockCode("passkey1", time.Hour),
newCode: mockEncryptedCode("passkey1", time.Hour),
eventstore: expectEventstore(),
idGenerator: id_mock.NewIDGeneratorExpectError(t, io.ErrClosedPipe),
},
@@ -488,7 +488,7 @@ func TestCommands_AddUserPasskeyCode(t *testing.T) {
{
name: "success",
fields: fields{
newCode: mockCode("passkey1", time.Minute),
newCode: mockEncryptedCode("passkey1", time.Minute),
eventstore: expectEventstore(
expectFilter(eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -530,9 +530,9 @@ func TestCommands_AddUserPasskeyCode(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Commands{
newCode: tt.fields.newCode,
eventstore: tt.fields.eventstore(t),
idGenerator: tt.fields.idGenerator,
newEncryptedCode: tt.fields.newCode,
eventstore: tt.fields.eventstore(t),
idGenerator: tt.fields.idGenerator,
}
got, err := c.AddUserPasskeyCode(context.Background(), tt.args.userID, tt.args.resourceOwner, alg)
require.ErrorIs(t, err, tt.wantErr)
@@ -546,7 +546,7 @@ func TestCommands_AddUserPasskeyCodeURLTemplate(t *testing.T) {
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
newCode cryptoCodeFunc
newCode encrypedCodeFunc
eventstore *eventstore.Eventstore
idGenerator id.Generator
}
@@ -565,7 +565,7 @@ func TestCommands_AddUserPasskeyCodeURLTemplate(t *testing.T) {
{
name: "template error",
fields: fields{
newCode: newCryptoCode,
newCode: newEncryptedCode,
eventstore: eventstoreExpect(t),
},
args: args{
@@ -578,7 +578,7 @@ func TestCommands_AddUserPasskeyCodeURLTemplate(t *testing.T) {
{
name: "id generator error",
fields: fields{
newCode: newCryptoCode,
newCode: newEncryptedCode,
eventstore: eventstoreExpect(t),
idGenerator: id_mock.NewIDGeneratorExpectError(t, io.ErrClosedPipe),
},
@@ -592,7 +592,7 @@ func TestCommands_AddUserPasskeyCodeURLTemplate(t *testing.T) {
{
name: "success",
fields: fields{
newCode: mockCode("passkey1", time.Minute),
newCode: mockEncryptedCode("passkey1", time.Minute),
eventstore: eventstoreExpect(t,
expectFilter(eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -638,9 +638,9 @@ func TestCommands_AddUserPasskeyCodeURLTemplate(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Commands{
newCode: tt.fields.newCode,
eventstore: tt.fields.eventstore,
idGenerator: tt.fields.idGenerator,
newEncryptedCode: tt.fields.newCode,
eventstore: tt.fields.eventstore,
idGenerator: tt.fields.idGenerator,
}
got, err := c.AddUserPasskeyCodeURLTemplate(context.Background(), tt.args.userID, tt.args.resourceOwner, alg, tt.args.urlTmpl)
require.ErrorIs(t, err, tt.wantErr)
@@ -653,7 +653,7 @@ func TestCommands_AddUserPasskeyCodeReturn(t *testing.T) {
alg := crypto.CreateMockEncryptionAlg(gomock.NewController(t))
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
newCode cryptoCodeFunc
newCode encrypedCodeFunc
eventstore *eventstore.Eventstore
idGenerator id.Generator
}
@@ -671,7 +671,7 @@ func TestCommands_AddUserPasskeyCodeReturn(t *testing.T) {
{
name: "id generator error",
fields: fields{
newCode: newCryptoCode,
newCode: newEncryptedCode,
eventstore: eventstoreExpect(t),
idGenerator: id_mock.NewIDGeneratorExpectError(t, io.ErrClosedPipe),
},
@@ -684,7 +684,7 @@ func TestCommands_AddUserPasskeyCodeReturn(t *testing.T) {
{
name: "success",
fields: fields{
newCode: mockCode("passkey1", time.Minute),
newCode: mockEncryptedCode("passkey1", time.Minute),
eventstore: eventstoreExpect(t,
expectFilter(eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -730,9 +730,9 @@ func TestCommands_AddUserPasskeyCodeReturn(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Commands{
newCode: tt.fields.newCode,
eventstore: tt.fields.eventstore,
idGenerator: tt.fields.idGenerator,
newEncryptedCode: tt.fields.newCode,
eventstore: tt.fields.eventstore,
idGenerator: tt.fields.idGenerator,
}
got, err := c.AddUserPasskeyCodeReturn(context.Background(), tt.args.userID, tt.args.resourceOwner, alg)
require.ErrorIs(t, err, tt.wantErr)
@@ -745,7 +745,7 @@ func TestCommands_addUserPasskeyCode(t *testing.T) {
alg := crypto.CreateMockEncryptionAlg(gomock.NewController(t))
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
newCode cryptoCodeFunc
newCode encrypedCodeFunc
eventstore *eventstore.Eventstore
idGenerator id.Generator
}
@@ -763,7 +763,7 @@ func TestCommands_addUserPasskeyCode(t *testing.T) {
{
name: "id generator error",
fields: fields{
newCode: newCryptoCode,
newCode: newEncryptedCode,
eventstore: eventstoreExpect(t),
idGenerator: id_mock.NewIDGeneratorExpectError(t, io.ErrClosedPipe),
},
@@ -776,7 +776,7 @@ func TestCommands_addUserPasskeyCode(t *testing.T) {
{
name: "crypto error",
fields: fields{
newCode: newCryptoCode,
newCode: newEncryptedCode,
eventstore: eventstoreExpect(t, expectFilterError(io.ErrClosedPipe)),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "123"),
},
@@ -789,7 +789,7 @@ func TestCommands_addUserPasskeyCode(t *testing.T) {
{
name: "filter query error",
fields: fields{
newCode: newCryptoCode,
newCode: newEncryptedCode,
eventstore: eventstoreExpect(t,
expectFilter(eventFromEventPusher(testSecretGeneratorAddedEvent(domain.SecretGeneratorTypePasswordlessInitCode))),
expectFilterError(io.ErrClosedPipe),
@@ -805,7 +805,7 @@ func TestCommands_addUserPasskeyCode(t *testing.T) {
{
name: "push error",
fields: fields{
newCode: mockCode("passkey1", time.Minute),
newCode: mockEncryptedCode("passkey1", time.Minute),
eventstore: eventstoreExpect(t,
expectFilter(eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -844,7 +844,7 @@ func TestCommands_addUserPasskeyCode(t *testing.T) {
{
name: "success",
fields: fields{
newCode: mockCode("passkey1", time.Minute),
newCode: mockEncryptedCode("passkey1", time.Minute),
eventstore: eventstoreExpect(t,
expectFilter(eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -890,9 +890,9 @@ func TestCommands_addUserPasskeyCode(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Commands{
newCode: tt.fields.newCode,
eventstore: tt.fields.eventstore,
idGenerator: tt.fields.idGenerator,
newEncryptedCode: tt.fields.newCode,
eventstore: tt.fields.eventstore,
idGenerator: tt.fields.idGenerator,
}
got, err := c.addUserPasskeyCode(context.Background(), tt.args.userID, tt.args.resourceOwner, alg, "", false)
require.ErrorIs(t, err, tt.wantErr)
+1 -1
View File
@@ -55,7 +55,7 @@ func (c *Commands) requestPasswordReset(ctx context.Context, userID string, retu
return nil, nil, err
}
}
code, err := c.newCode(ctx, c.eventstore.Filter, domain.SecretGeneratorTypePasswordResetCode, c.userEncryption)
code, err := c.newEncryptedCode(ctx, c.eventstore.Filter, domain.SecretGeneratorTypePasswordResetCode, c.userEncryption) //nolint:staticcheck
if err != nil {
return nil, nil, err
}
+9 -9
View File
@@ -330,7 +330,7 @@ func TestCommands_requestPasswordReset(t *testing.T) {
checkPermission domain.PermissionCheck
eventstore func(t *testing.T) *eventstore.Eventstore
userEncryption crypto.EncryptionAlgorithm
newCode cryptoCodeFunc
newCode encrypedCodeFunc
}
type args struct {
ctx context.Context
@@ -452,7 +452,7 @@ func TestCommands_requestPasswordReset(t *testing.T) {
),
),
checkPermission: newMockPermissionCheckAllowed(),
newCode: mockCode("code", 10*time.Minute),
newCode: mockEncryptedCode("code", 10*time.Minute),
},
args: args{
ctx: context.Background(),
@@ -492,7 +492,7 @@ func TestCommands_requestPasswordReset(t *testing.T) {
),
),
checkPermission: newMockPermissionCheckAllowed(),
newCode: mockCode("code", 10*time.Minute),
newCode: mockEncryptedCode("code", 10*time.Minute),
},
args: args{
ctx: context.Background(),
@@ -533,7 +533,7 @@ func TestCommands_requestPasswordReset(t *testing.T) {
),
),
checkPermission: newMockPermissionCheckAllowed(),
newCode: mockCode("code", 10*time.Minute),
newCode: mockEncryptedCode("code", 10*time.Minute),
},
args: args{
ctx: context.Background(),
@@ -575,7 +575,7 @@ func TestCommands_requestPasswordReset(t *testing.T) {
),
),
checkPermission: newMockPermissionCheckAllowed(),
newCode: mockCode("code", 10*time.Minute),
newCode: mockEncryptedCode("code", 10*time.Minute),
},
args: args{
ctx: context.Background(),
@@ -593,10 +593,10 @@ func TestCommands_requestPasswordReset(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Commands{
checkPermission: tt.fields.checkPermission,
eventstore: tt.fields.eventstore(t),
userEncryption: tt.fields.userEncryption,
newCode: tt.fields.newCode,
checkPermission: tt.fields.checkPermission,
eventstore: tt.fields.eventstore(t),
userEncryption: tt.fields.userEncryption,
newEncryptedCode: tt.fields.newCode,
}
got, gotPlainCode, err := c.requestPasswordReset(tt.args.ctx, tt.args.userID, tt.args.returnCode, tt.args.urlTmpl, tt.args.notificationType)
require.ErrorIs(t, err, tt.res.err)
+4 -4
View File
@@ -55,7 +55,7 @@ func (c *Commands) ResendUserPhoneCodeReturnCode(ctx context.Context, userID str
}
func (c *Commands) changeUserPhoneWithCode(ctx context.Context, userID, phone string, alg crypto.EncryptionAlgorithm, returnCode bool) (*domain.Phone, error) {
config, err := secretGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyPhoneCode)
config, err := cryptoGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyPhoneCode) //nolint:staticcheck
if err != nil {
return nil, err
}
@@ -64,7 +64,7 @@ func (c *Commands) changeUserPhoneWithCode(ctx context.Context, userID, phone st
}
func (c *Commands) resendUserPhoneCode(ctx context.Context, userID string, alg crypto.EncryptionAlgorithm, returnCode bool) (*domain.Phone, error) {
config, err := secretGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyPhoneCode) //nolint:staticcheck
config, err := cryptoGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyPhoneCode) //nolint:staticcheck
if err != nil {
return nil, err
}
@@ -117,7 +117,7 @@ func (c *Commands) resendUserPhoneCodeWithGenerator(ctx context.Context, userID
}
func (c *Commands) VerifyUserPhone(ctx context.Context, userID, code string, alg crypto.EncryptionAlgorithm) (*domain.ObjectDetails, error) {
config, err := secretGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyPhoneCode)
config, err := cryptoGeneratorConfig(ctx, c.eventstore.Filter, domain.SecretGeneratorTypeVerifyPhoneCode) //nolint:staticcheck
if err != nil {
return nil, err
}
@@ -216,7 +216,7 @@ func (c *UserPhoneEvents) VerifyCode(ctx context.Context, code string, gen crypt
return zerrors.ThrowInvalidArgument(nil, "COMMAND-Fia4a", "Errors.User.Code.Empty")
}
err := crypto.VerifyCode(c.model.CodeCreationDate, c.model.CodeExpiry, c.model.Code, code, gen)
err := crypto.VerifyCode(c.model.CodeCreationDate, c.model.CodeExpiry, c.model.Code, code, gen.Alg())
if err == nil {
c.events = append(c.events, user.NewHumanPhoneVerifiedEvent(ctx, c.aggregate))
return nil