mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-09 07:35:13 +00:00
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:
co-authored by
Livio Spring
parent
5931fb8f28
commit
2089992d75
+32
-23
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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$"},
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user