diff --git a/cmd/hashers/argon2/root.go b/cmd/hashers/argon2/root.go index ad8fa1dc68d7..763107dfab53 100644 --- a/cmd/hashers/argon2/root.go +++ b/cmd/hashers/argon2/root.go @@ -3,6 +3,7 @@ package argon2 import ( "context" "fmt" + "github.com/ory/kratos/hash" "reflect" "strings" @@ -76,7 +77,7 @@ func configProvider(cmd *cobra.Command, flagConf *argon2Config) (*argon2Config, _, _ = fmt.Fprintf(cmd.ErrOrStderr(), "Unable to initialize the config provider: %s\n", err) return nil, cmdx.FailSilently(cmd) } - conf.localConfig = *conf.config.HasherArgon2() + conf.localConfig = (config.Argon2)(*conf.config.HasherArgon2()) if cmd.Flags().Changed(FlagIterations) { conf.localConfig.Iterations = flagConf.localConfig.Iterations @@ -162,6 +163,10 @@ func (c *argon2Config) Config(_ context.Context) *config.Config { return c.config } +func (c *argon2Config) HashConfig(ctx context.Context) hash.HashConfigProvider { + return c.Config(ctx) +} + func (c *argon2Config) HasherArgon2() (*config.Argon2, error) { if c.localConfig.Memory == 0 { c.localConfig.Memory = config.Argon2DefaultMemory diff --git a/driver/config/config.go b/driver/config/config.go index 116d5d17b472..3bdbf7ae09f7 100644 --- a/driver/config/config.go +++ b/driver/config/config.go @@ -6,6 +6,7 @@ import ( "crypto/tls" "encoding/json" "fmt" + "github.com/ory/kratos/hash" "io" "net" "net/http" @@ -169,19 +170,9 @@ const ( const DefaultSessionCookieName = "ory_kratos_session" type ( - Argon2 struct { - Memory bytesize.ByteSize `json:"memory"` - Iterations uint32 `json:"iterations"` - Parallelism uint8 `json:"parallelism"` - SaltLength uint32 `json:"salt_length"` - KeyLength uint32 `json:"key_length"` - ExpectedDuration time.Duration `json:"expected_duration"` - ExpectedDeviation time.Duration `json:"expected_deviation"` - DedicatedMemory bytesize.ByteSize `json:"dedicated_memory"` - } - Bcrypt struct { - Cost uint32 `json:"cost"` - } + Argon2 hash.Argon2Config + Bcrypt hash.BcryptConfig + SelfServiceHook struct { Name string `json:"hook"` Config json.RawMessage `json:"config"` @@ -210,6 +201,7 @@ type ( Provider interface { Config(ctx context.Context) *Config + hash.ConfigProvider } ) @@ -389,10 +381,10 @@ func (p *Config) SessionName() string { return stringsx.Coalesce(p.p.String(ViperKeySessionName), DefaultSessionCookieName) } -func (p *Config) HasherArgon2() *Argon2 { +func (p *Config) HasherArgon2() *hash.Argon2Config { // warn about usage of default values and point to the docs // warning will require https://github.com/ory/viper/issues/19 - return &Argon2{ + return &hash.Argon2Config{ Memory: p.p.ByteSizeF(ViperKeyHasherArgon2ConfigMemory, Argon2DefaultMemory), Iterations: uint32(p.p.IntF(ViperKeyHasherArgon2ConfigIterations, int(Argon2DefaultIterations))), Parallelism: uint8(p.p.IntF(ViperKeyHasherArgon2ConfigParallelism, int(Argon2DefaultParallelism))), @@ -404,7 +396,7 @@ func (p *Config) HasherArgon2() *Argon2 { } } -func (p *Config) HasherBcrypt() *Bcrypt { +func (p *Config) HasherBcrypt() *hash.BcryptConfig { // warn about usage of default values and point to the docs // warning will require https://github.com/ory/viper/issues/19 cost := uint32(p.p.IntF(ViperKeyHasherBcryptCost, int(BcryptDefaultCost))) @@ -412,7 +404,7 @@ func (p *Config) HasherBcrypt() *Bcrypt { cost = BcryptDefaultCost } - return &Bcrypt{Cost: cost} + return &hash.BcryptConfig{Cost: cost} } func (p *Config) listenOn(key string) string { @@ -1069,6 +1061,10 @@ func (p *Config) HasherPasswordHashingAlgorithm() string { } } +func (p *Config) Hasher(provider hash.ConfigProvider) hash.Hasher { + return hash.NewHasher(p.HasherPasswordHashingAlgorithm(), provider) +} + func (p *Config) CipherAlgorithm() string { configValue := p.p.StringF(ViperKeyCipherAlgorithm, DefaultCipherAlgorithm) switch configValue { diff --git a/driver/registry.go b/driver/registry.go index 4c5c2190f0d4..baa733c41a56 100644 --- a/driver/registry.go +++ b/driver/registry.go @@ -79,7 +79,7 @@ type Registry interface { errorx.HandlerProvider errorx.PersistenceProvider - hash.HashProvider + hash.Generator identity.HandlerProvider identity.ValidationProvider diff --git a/driver/registry_default.go b/driver/registry_default.go index c6fe37a9eeba..ffff766ed1fc 100644 --- a/driver/registry_default.go +++ b/driver/registry_default.go @@ -259,6 +259,10 @@ func (m *RegistryDefault) Config(ctx context.Context) *config.Config { return corp.ContextualizeConfig(ctx, m.c) } +func (m *RegistryDefault) HashConfig(ctx context.Context) hash.HashConfigProvider { + return m.Config(ctx) +} + func (m *RegistryDefault) selfServiceStrategies() []interface{} { if len(m.selfserviceStrategies) == 0 { m.selfserviceStrategies = []interface{}{ @@ -392,11 +396,7 @@ func (m *RegistryDefault) Cipher() cipher.Cipher { func (m *RegistryDefault) Hasher() hash.Hasher { if m.passwordHasher == nil { - if m.c.HasherPasswordHashingAlgorithm() == "bcrypt" { - m.passwordHasher = hash.NewHasherBcrypt(m) - } else { - m.passwordHasher = hash.NewHasherArgon2(m) - } + m.passwordHasher = m.c.Hasher(m) } return m.passwordHasher } diff --git a/hash/hash_comparator.go b/hash/hash_comparator.go index 00a11a89934d..27c4cffaeb2b 100644 --- a/hash/hash_comparator.go +++ b/hash/hash_comparator.go @@ -12,8 +12,6 @@ import ( "golang.org/x/crypto/argon2" "golang.org/x/crypto/bcrypt" "golang.org/x/crypto/pbkdf2" - - "github.com/ory/kratos/driver/config" ) var ErrUnknownHashAlgorithm = errors.New("unknown hash algorithm") @@ -102,7 +100,7 @@ func IsPbkdf2Hash(hash []byte) bool { return isPbkdf2Hash.Match(hash) } -func decodeArgon2idHash(encodedHash string) (p *config.Argon2, salt, hash []byte, err error) { +func decodeArgon2idHash(encodedHash string) (p *Argon2Config, salt, hash []byte, err error) { parts := strings.Split(encodedHash, "$") if len(parts) != 6 { return nil, nil, nil, ErrInvalidHash @@ -117,7 +115,7 @@ func decodeArgon2idHash(encodedHash string) (p *config.Argon2, salt, hash []byte return nil, nil, nil, ErrIncompatibleVersion } - p = new(config.Argon2) + p = new(Argon2Config) _, err = fmt.Sscanf(parts[3], "m=%d,t=%d,p=%d", &p.Memory, &p.Iterations, &p.Parallelism) if err != nil { return nil, nil, nil, err diff --git a/hash/hasher.go b/hash/hasher.go index 8398ae293393..ccba95d101fc 100644 --- a/hash/hasher.go +++ b/hash/hasher.go @@ -1,6 +1,10 @@ package hash -import "context" +import ( + "context" + "github.com/inhies/go-bytesize" + "time" +) // Hasher provides methods for generating and comparing password hashes. type Hasher interface { @@ -11,6 +15,41 @@ type Hasher interface { Understands(hash []byte) bool } -type HashProvider interface { +// Generator is the interface that objects that can construct hashers must implement +type Generator interface { Hasher() Hasher } + +// HashConfigProvider is the interface that objects that can generate configuration for the implemented hashers must +// implement +type HashConfigProvider interface { + HasherBcrypt() *BcryptConfig + HasherArgon2() *Argon2Config +} + +type BcryptConfig struct { + Cost uint32 `json:"cost"` +} + +type Argon2Config struct { + Memory bytesize.ByteSize `json:"memory"` + Iterations uint32 `json:"iterations"` + Parallelism uint8 `json:"parallelism"` + SaltLength uint32 `json:"salt_length"` + KeyLength uint32 `json:"key_length"` + ExpectedDuration time.Duration `json:"expected_duration"` + ExpectedDeviation time.Duration `json:"expected_deviation"` + DedicatedMemory bytesize.ByteSize `json:"dedicated_memory"` +} + +type ConfigProvider interface { + HashConfig(ctx context.Context) HashConfigProvider +} + +func NewHasher(algorithm string, provider ConfigProvider) Hasher { + if algorithm == "bcrypt" { + return NewHasherBcrypt(provider) + } else { + return NewHasherArgon2(provider) + } +} diff --git a/hash/hasher_argon2.go b/hash/hasher_argon2.go index 6280518df860..92b490664924 100644 --- a/hash/hasher_argon2.go +++ b/hash/hasher_argon2.go @@ -11,8 +11,6 @@ import ( "github.com/pkg/errors" "golang.org/x/crypto/argon2" - - "github.com/ory/kratos/driver/config" ) var ( @@ -26,7 +24,7 @@ type Argon2 struct { } type Argon2Configuration interface { - config.Provider + ConfigProvider } func NewHasherArgon2(c Argon2Configuration) *Argon2 { @@ -38,7 +36,7 @@ func toKB(mem bytesize.ByteSize) uint32 { } func (h *Argon2) Generate(ctx context.Context, password []byte) ([]byte, error) { - p := h.c.Config(ctx).HasherArgon2() + p := h.c.HashConfig(ctx).HasherArgon2() salt := make([]byte, p.SaltLength) if _, err := rand.Read(salt); err != nil { diff --git a/hash/hasher_bcrypt.go b/hash/hasher_bcrypt.go index 4f23a58e4246..e239d651752e 100644 --- a/hash/hasher_bcrypt.go +++ b/hash/hasher_bcrypt.go @@ -2,12 +2,8 @@ package hash import ( "context" - - "github.com/ory/kratos/schema" - + "github.com/ory/kratos/schema/errors" "golang.org/x/crypto/bcrypt" - - "github.com/ory/kratos/driver/config" ) type Bcrypt struct { @@ -15,7 +11,7 @@ type Bcrypt struct { } type BcryptConfiguration interface { - config.Provider + ConfigProvider } func NewHasherBcrypt(c BcryptConfiguration) *Bcrypt { @@ -27,7 +23,7 @@ func (h *Bcrypt) Generate(ctx context.Context, password []byte) ([]byte, error) return nil, err } - hash, err := bcrypt.GenerateFromPassword(password, int(h.c.Config(ctx).HasherBcrypt().Cost)) + hash, err := bcrypt.GenerateFromPassword(password, int(h.c.HashConfig(ctx).HasherBcrypt().Cost)) if err != nil { return nil, err } @@ -40,7 +36,7 @@ func validateBcryptPasswordLength(password []byte) error { // so if password is longer than 72 bytes, function returns an error // See https://en.wikipedia.org/wiki/Bcrypt#User_input if len(password) > 72 { - return schema.NewPasswordPolicyViolationError( + return errors.NewPasswordPolicyViolationError( "#/password", "passwords are limited to a maximum length of 72 characters", ) diff --git a/identity/handler.go b/identity/handler.go index 7c28d2614712..22b8e4a13fc4 100644 --- a/identity/handler.go +++ b/identity/handler.go @@ -22,8 +22,11 @@ import ( "github.com/ory/kratos/driver/config" ) -const RouteCollection = "/identities" -const RouteItem = RouteCollection + "/:id" +const ( + RouteCollection = "/identities" + RouteItem = RouteCollection + "/:id" + Bcrypt = "bcrypt" +) type ( handlerDependencies interface { @@ -205,6 +208,30 @@ type adminCreateIdentity struct { Body AdminCreateIdentityBody } +// CredentialsConfig is the struct that is being used as part of the identity credentials. +type CredentialsConfig struct { + // HashedPassword is a hash-representation of the password. + HashedPassword string `json:"hashed_password"` +} + +// User's password +// +// The password of the user. It represents a cleartext or hashed user password. +// +// swagger:model passwordCredential +type PasswordCredential struct { + // Value represents the value of the password in clear text or hashed + // + // required: true + Value string `json:"value"` + + // This field must be true if the value represents a hashed password. Otherwise the value is assumed to be a + // cleartext password and it will be hashed before storing. + // + // required: true + IsHashed bool `json:"is_hashed"` +} + // swagger:model adminCreateIdentityBody type AdminCreateIdentityBody struct { // SchemaID is the ID of the JSON Schema to be used for validating the identity's traits. @@ -219,19 +246,61 @@ type AdminCreateIdentityBody struct { // required: true Traits json.RawMessage `json:"traits"` + // Password for the user. This will only be used if the json schema actually defines the + // password as a valid type. + // + // required: false + Password *PasswordCredential `json:"password"` + // State is the identity's state. // // required: false State State `json:"state"` + + // VerifiableAddresses contains all the addresses that can be verified by the user. + // + // required: false + VerifiableAddresses []VerifiableAddress `json:"verifiable_addresses"` +} + +func (h *Handler) parsePwdCredential(i *Identity, cr AdminCreateIdentityBody, ctx context.Context) error { + if cr.Password != nil { + // Create the credentials + hpw := []byte(cr.Password.Value) + if !cr.Password.IsHashed { + var err error + + if hpw, err = h.r.Config(ctx).Hasher(h.r).Generate(ctx, hpw); err != nil { + return errors.WithStack(herodot.ErrBadRequest.WithReasonf("%s", err).WithWrap(err)) + } + } + + config, err := json.Marshal(&CredentialsConfig{ + HashedPassword: string(hpw), + }) + if err != nil { + return errors.WithStack(herodot.ErrBadRequest.WithReasonf("Unable to encode password options to JSON: %s", err).WithWrap(err)) + } + + i.Credentials = map[CredentialsType]Credentials{ + CredentialsTypePassword: { + Type: CredentialsTypePassword, + Identifiers: []string{}, + Config: config, + }, + } + } + return nil } // swagger:route POST /identities v0alpha2 adminCreateIdentity // // Create an Identity // -// This endpoint creates an identity. It is NOT possible to set an identity's credentials (password, ...) -// using this method! A way to achieve that will be introduced in the future. -// +// This endpoint creates an identity. Optionally a password can be set for the newly created identity. Do to so +// a password field must be included on the creation request. The password field can be in cleartext or hashed with +// any of the supported hashing algorithms. Using already hashed values can be useful when moving from another user +// authentication mechanism to Kratos. // Learn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model). // // Consumes: @@ -266,7 +335,20 @@ func (h *Handler) create(w http.ResponseWriter, r *http.Request, _ httprouter.Pa } state = cr.State } - i := &Identity{SchemaID: cr.SchemaID, Traits: []byte(cr.Traits), State: state, StateChangedAt: &stateChangedAt} + + i := &Identity{ + SchemaID: cr.SchemaID, + Traits: []byte(cr.Traits), + State: state, + StateChangedAt: &stateChangedAt, + VerifiableAddresses: cr.VerifiableAddresses, + } + + if err := h.parsePwdCredential(i, cr, r.Context()); err != nil { + h.r.Writer().WriteError(w, r, err) + return + } + if err := h.r.IdentityManager().Create(r.Context(), i); err != nil { h.r.Writer().WriteError(w, r, err) return diff --git a/internal/httpclient/.openapi-generator/FILES b/internal/httpclient/.openapi-generator/FILES index 266b1a529acc..8c7dbb8fe606 100644 --- a/internal/httpclient/.openapi-generator/FILES +++ b/internal/httpclient/.openapi-generator/FILES @@ -26,6 +26,7 @@ docs/InlineResponse503.md docs/JsonError.md docs/MetadataApi.md docs/NeedsPrivilegedSessionError.md +docs/PasswordCredential.md docs/RecoveryAddress.md docs/SelfServiceBrowserLocationChangeRequiredError.md docs/SelfServiceError.md @@ -101,6 +102,7 @@ model_inline_response_200_1.go model_inline_response_503.go model_json_error.go model_needs_privileged_session_error.go +model_password_credential.go model_recovery_address.go model_self_service_browser_location_change_required_error.go model_self_service_error.go diff --git a/internal/httpclient/README.md b/internal/httpclient/README.md index 6df00ecda261..8b98b2fb8143 100644 --- a/internal/httpclient/README.md +++ b/internal/httpclient/README.md @@ -143,6 +143,7 @@ Class | Method | HTTP request | Description - [InlineResponse503](docs/InlineResponse503.md) - [JsonError](docs/JsonError.md) - [NeedsPrivilegedSessionError](docs/NeedsPrivilegedSessionError.md) + - [PasswordCredential](docs/PasswordCredential.md) - [RecoveryAddress](docs/RecoveryAddress.md) - [SelfServiceBrowserLocationChangeRequiredError](docs/SelfServiceBrowserLocationChangeRequiredError.md) - [SelfServiceError](docs/SelfServiceError.md) diff --git a/internal/httpclient/api/openapi.yaml b/internal/httpclient/api/openapi.yaml index 46d1ddf0d473..a4396853fbdf 100644 --- a/internal/httpclient/api/openapi.yaml +++ b/internal/httpclient/api/openapi.yaml @@ -147,9 +147,10 @@ paths: - v0alpha2 post: description: |- - This endpoint creates an identity. It is NOT possible to set an identity's credentials (password, ...) - using this method! A way to achieve that will be introduced in the future. - + This endpoint creates an identity. Optionally a password can be set for the newly created identity. Do to so + a password field must be included on the creation request. The password field can be in cleartext or hashed with + any of the supported hashing algorithms. Using already hashed values can be useful when moving from another user + authentication mechanism to Kratos. Learn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model). operationId: adminCreateIdentity requestBody: @@ -2355,6 +2356,8 @@ components: type: string adminCreateIdentityBody: properties: + password: + $ref: '#/components/schemas/passwordCredential' schema_id: description: SchemaID is the ID of the JSON Schema to be used for validating the identity's traits. @@ -2367,6 +2370,12 @@ components: in a self-service manner. The input will always be validated against the JSON Schema defined in `schema_url`. type: object + verifiable_addresses: + description: VerifiableAddresses contains all the addresses that can be + verified by the user. + items: + $ref: '#/components/schemas/verifiableIdentityAddress' + type: array required: - schema_id - traits @@ -2787,6 +2796,24 @@ components: format: date-time title: NullTime implements sql.NullTime functionality. type: string + passwordCredential: + description: The password of the user. It represents a cleartext or hashed user + password. + properties: + is_hashed: + description: |- + This field must be true if the value represents a hashed password. Otherwise the value is assumed to be a + cleartext password and it will be hashed before storing. + type: boolean + value: + description: Value represents the value of the password in clear text or + hashed + type: string + required: + - is_hashed + - value + title: User's password + type: object selfServiceBrowserLocationChangeRequiredError: properties: code: diff --git a/internal/httpclient/api_v0alpha2.go b/internal/httpclient/api_v0alpha2.go index fe47c787540d..952add718e94 100644 --- a/internal/httpclient/api_v0alpha2.go +++ b/internal/httpclient/api_v0alpha2.go @@ -30,9 +30,10 @@ type V0alpha2Api interface { /* * AdminCreateIdentity Create an Identity - * This endpoint creates an identity. It is NOT possible to set an identity's credentials (password, ...) - using this method! A way to achieve that will be introduced in the future. - + * This endpoint creates an identity. Optionally a password can be set for the newly created identity. Do to so + a password field must be included on the creation request. The password field can be in cleartext or hashed with + any of the supported hashing algorithms. Using already hashed values can be useful when moving from another user + authentication mechanism to Kratos. Learn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model). * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @return V0alpha2ApiApiAdminCreateIdentityRequest @@ -1036,9 +1037,10 @@ func (r V0alpha2ApiApiAdminCreateIdentityRequest) Execute() (*Identity, *http.Re /* * AdminCreateIdentity Create an Identity - * This endpoint creates an identity. It is NOT possible to set an identity's credentials (password, ...) -using this method! A way to achieve that will be introduced in the future. - + * This endpoint creates an identity. Optionally a password can be set for the newly created identity. Do to so +a password field must be included on the creation request. The password field can be in cleartext or hashed with +any of the supported hashing algorithms. Using already hashed values can be useful when moving from another user +authentication mechanism to Kratos. Learn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model). * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @return V0alpha2ApiApiAdminCreateIdentityRequest diff --git a/internal/httpclient/docs/AdminCreateIdentityBody.md b/internal/httpclient/docs/AdminCreateIdentityBody.md index c56a9147263b..b9d290bff7bd 100644 --- a/internal/httpclient/docs/AdminCreateIdentityBody.md +++ b/internal/httpclient/docs/AdminCreateIdentityBody.md @@ -4,9 +4,11 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**Password** | Pointer to [**PasswordCredential**](PasswordCredential.md) | | [optional] **SchemaId** | **string** | SchemaID is the ID of the JSON Schema to be used for validating the identity's traits. | **State** | Pointer to [**IdentityState**](IdentityState.md) | | [optional] **Traits** | **map[string]interface{}** | Traits represent an identity's traits. The identity is able to create, modify, and delete traits in a self-service manner. The input will always be validated against the JSON Schema defined in `schema_url`. | +**VerifiableAddresses** | Pointer to [**[]VerifiableIdentityAddress**](VerifiableIdentityAddress.md) | VerifiableAddresses contains all the addresses that can be verified by the user. | [optional] ## Methods @@ -27,6 +29,31 @@ NewAdminCreateIdentityBodyWithDefaults instantiates a new AdminCreateIdentityBod This constructor will only assign default values to properties that have it defined, but it doesn't guarantee that properties required by API are set +### GetPassword + +`func (o *AdminCreateIdentityBody) GetPassword() PasswordCredential` + +GetPassword returns the Password field if non-nil, zero value otherwise. + +### GetPasswordOk + +`func (o *AdminCreateIdentityBody) GetPasswordOk() (*PasswordCredential, bool)` + +GetPasswordOk returns a tuple with the Password field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetPassword + +`func (o *AdminCreateIdentityBody) SetPassword(v PasswordCredential)` + +SetPassword sets Password field to given value. + +### HasPassword + +`func (o *AdminCreateIdentityBody) HasPassword() bool` + +HasPassword returns a boolean if a field has been set. + ### GetSchemaId `func (o *AdminCreateIdentityBody) GetSchemaId() string` @@ -92,6 +119,31 @@ and a boolean to check if the value has been set. SetTraits sets Traits field to given value. +### GetVerifiableAddresses + +`func (o *AdminCreateIdentityBody) GetVerifiableAddresses() []VerifiableIdentityAddress` + +GetVerifiableAddresses returns the VerifiableAddresses field if non-nil, zero value otherwise. + +### GetVerifiableAddressesOk + +`func (o *AdminCreateIdentityBody) GetVerifiableAddressesOk() (*[]VerifiableIdentityAddress, bool)` + +GetVerifiableAddressesOk returns a tuple with the VerifiableAddresses field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetVerifiableAddresses + +`func (o *AdminCreateIdentityBody) SetVerifiableAddresses(v []VerifiableIdentityAddress)` + +SetVerifiableAddresses sets VerifiableAddresses field to given value. + +### HasVerifiableAddresses + +`func (o *AdminCreateIdentityBody) HasVerifiableAddresses() bool` + +HasVerifiableAddresses returns a boolean if a field has been set. + [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/internal/httpclient/docs/PasswordCredential.md b/internal/httpclient/docs/PasswordCredential.md new file mode 100644 index 000000000000..715440947a05 --- /dev/null +++ b/internal/httpclient/docs/PasswordCredential.md @@ -0,0 +1,72 @@ +# PasswordCredential + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**IsHashed** | **bool** | This field must be true if the value represents a hashed password. Otherwise the value is assumed to be a cleartext password and it will be hashed before storing. | +**Value** | **string** | Value represents the value of the password in clear text or hashed | + +## Methods + +### NewPasswordCredential + +`func NewPasswordCredential(isHashed bool, value string, ) *PasswordCredential` + +NewPasswordCredential instantiates a new PasswordCredential object +This constructor will assign default values to properties that have it defined, +and makes sure properties required by API are set, but the set of arguments +will change when the set of required properties is changed + +### NewPasswordCredentialWithDefaults + +`func NewPasswordCredentialWithDefaults() *PasswordCredential` + +NewPasswordCredentialWithDefaults instantiates a new PasswordCredential object +This constructor will only assign default values to properties that have it defined, +but it doesn't guarantee that properties required by API are set + +### GetIsHashed + +`func (o *PasswordCredential) GetIsHashed() bool` + +GetIsHashed returns the IsHashed field if non-nil, zero value otherwise. + +### GetIsHashedOk + +`func (o *PasswordCredential) GetIsHashedOk() (*bool, bool)` + +GetIsHashedOk returns a tuple with the IsHashed field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetIsHashed + +`func (o *PasswordCredential) SetIsHashed(v bool)` + +SetIsHashed sets IsHashed field to given value. + + +### GetValue + +`func (o *PasswordCredential) GetValue() string` + +GetValue returns the Value field if non-nil, zero value otherwise. + +### GetValueOk + +`func (o *PasswordCredential) GetValueOk() (*string, bool)` + +GetValueOk returns a tuple with the Value field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetValue + +`func (o *PasswordCredential) SetValue(v string)` + +SetValue sets Value field to given value. + + + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/internal/httpclient/model_admin_create_identity_body.go b/internal/httpclient/model_admin_create_identity_body.go index 5f85e9262bb9..5a94a8921a76 100644 --- a/internal/httpclient/model_admin_create_identity_body.go +++ b/internal/httpclient/model_admin_create_identity_body.go @@ -17,11 +17,14 @@ import ( // AdminCreateIdentityBody struct for AdminCreateIdentityBody type AdminCreateIdentityBody struct { + Password *PasswordCredential `json:"password,omitempty"` // SchemaID is the ID of the JSON Schema to be used for validating the identity's traits. SchemaId string `json:"schema_id"` State *IdentityState `json:"state,omitempty"` // Traits represent an identity's traits. The identity is able to create, modify, and delete traits in a self-service manner. The input will always be validated against the JSON Schema defined in `schema_url`. Traits map[string]interface{} `json:"traits"` + // VerifiableAddresses contains all the addresses that can be verified by the user. + VerifiableAddresses []VerifiableIdentityAddress `json:"verifiable_addresses,omitempty"` } // NewAdminCreateIdentityBody instantiates a new AdminCreateIdentityBody object @@ -43,6 +46,38 @@ func NewAdminCreateIdentityBodyWithDefaults() *AdminCreateIdentityBody { return &this } +// GetPassword returns the Password field value if set, zero value otherwise. +func (o *AdminCreateIdentityBody) GetPassword() PasswordCredential { + if o == nil || o.Password == nil { + var ret PasswordCredential + return ret + } + return *o.Password +} + +// GetPasswordOk returns a tuple with the Password field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AdminCreateIdentityBody) GetPasswordOk() (*PasswordCredential, bool) { + if o == nil || o.Password == nil { + return nil, false + } + return o.Password, true +} + +// HasPassword returns a boolean if a field has been set. +func (o *AdminCreateIdentityBody) HasPassword() bool { + if o != nil && o.Password != nil { + return true + } + + return false +} + +// SetPassword gets a reference to the given PasswordCredential and assigns it to the Password field. +func (o *AdminCreateIdentityBody) SetPassword(v PasswordCredential) { + o.Password = &v +} + // GetSchemaId returns the SchemaId field value func (o *AdminCreateIdentityBody) GetSchemaId() string { if o == nil { @@ -123,8 +158,43 @@ func (o *AdminCreateIdentityBody) SetTraits(v map[string]interface{}) { o.Traits = v } +// GetVerifiableAddresses returns the VerifiableAddresses field value if set, zero value otherwise. +func (o *AdminCreateIdentityBody) GetVerifiableAddresses() []VerifiableIdentityAddress { + if o == nil || o.VerifiableAddresses == nil { + var ret []VerifiableIdentityAddress + return ret + } + return o.VerifiableAddresses +} + +// GetVerifiableAddressesOk returns a tuple with the VerifiableAddresses field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *AdminCreateIdentityBody) GetVerifiableAddressesOk() ([]VerifiableIdentityAddress, bool) { + if o == nil || o.VerifiableAddresses == nil { + return nil, false + } + return o.VerifiableAddresses, true +} + +// HasVerifiableAddresses returns a boolean if a field has been set. +func (o *AdminCreateIdentityBody) HasVerifiableAddresses() bool { + if o != nil && o.VerifiableAddresses != nil { + return true + } + + return false +} + +// SetVerifiableAddresses gets a reference to the given []VerifiableIdentityAddress and assigns it to the VerifiableAddresses field. +func (o *AdminCreateIdentityBody) SetVerifiableAddresses(v []VerifiableIdentityAddress) { + o.VerifiableAddresses = v +} + func (o AdminCreateIdentityBody) MarshalJSON() ([]byte, error) { toSerialize := map[string]interface{}{} + if o.Password != nil { + toSerialize["password"] = o.Password + } if true { toSerialize["schema_id"] = o.SchemaId } @@ -134,6 +204,9 @@ func (o AdminCreateIdentityBody) MarshalJSON() ([]byte, error) { if true { toSerialize["traits"] = o.Traits } + if o.VerifiableAddresses != nil { + toSerialize["verifiable_addresses"] = o.VerifiableAddresses + } return json.Marshal(toSerialize) } diff --git a/internal/httpclient/model_password_credential.go b/internal/httpclient/model_password_credential.go new file mode 100644 index 000000000000..c7bf680798ec --- /dev/null +++ b/internal/httpclient/model_password_credential.go @@ -0,0 +1,138 @@ +/* + * Ory Kratos API + * + * Documentation for all public and administrative Ory Kratos APIs. Public and administrative APIs are exposed on different ports. Public APIs can face the public internet without any protection while administrative APIs should never be exposed without prior authorization. To protect the administative API port you should use something like Nginx, Ory Oathkeeper, or any other technology capable of authorizing incoming requests. + * + * API version: 1.0.0 + * Contact: hi@ory.sh + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package client + +import ( + "encoding/json" +) + +// PasswordCredential The password of the user. It represents a cleartext or hashed user password. +type PasswordCredential struct { + // This field must be true if the value represents a hashed password. Otherwise the value is assumed to be a cleartext password and it will be hashed before storing. + IsHashed bool `json:"is_hashed"` + // Value represents the value of the password in clear text or hashed + Value string `json:"value"` +} + +// NewPasswordCredential instantiates a new PasswordCredential object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPasswordCredential(isHashed bool, value string) *PasswordCredential { + this := PasswordCredential{} + this.IsHashed = isHashed + this.Value = value + return &this +} + +// NewPasswordCredentialWithDefaults instantiates a new PasswordCredential object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPasswordCredentialWithDefaults() *PasswordCredential { + this := PasswordCredential{} + return &this +} + +// GetIsHashed returns the IsHashed field value +func (o *PasswordCredential) GetIsHashed() bool { + if o == nil { + var ret bool + return ret + } + + return o.IsHashed +} + +// GetIsHashedOk returns a tuple with the IsHashed field value +// and a boolean to check if the value has been set. +func (o *PasswordCredential) GetIsHashedOk() (*bool, bool) { + if o == nil { + return nil, false + } + return &o.IsHashed, true +} + +// SetIsHashed sets field value +func (o *PasswordCredential) SetIsHashed(v bool) { + o.IsHashed = v +} + +// GetValue returns the Value field value +func (o *PasswordCredential) GetValue() string { + if o == nil { + var ret string + return ret + } + + return o.Value +} + +// GetValueOk returns a tuple with the Value field value +// and a boolean to check if the value has been set. +func (o *PasswordCredential) GetValueOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Value, true +} + +// SetValue sets field value +func (o *PasswordCredential) SetValue(v string) { + o.Value = v +} + +func (o PasswordCredential) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["is_hashed"] = o.IsHashed + } + if true { + toSerialize["value"] = o.Value + } + return json.Marshal(toSerialize) +} + +type NullablePasswordCredential struct { + value *PasswordCredential + isSet bool +} + +func (v NullablePasswordCredential) Get() *PasswordCredential { + return v.value +} + +func (v *NullablePasswordCredential) Set(val *PasswordCredential) { + v.value = val + v.isSet = true +} + +func (v NullablePasswordCredential) IsSet() bool { + return v.isSet +} + +func (v *NullablePasswordCredential) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePasswordCredential(val *PasswordCredential) *NullablePasswordCredential { + return &NullablePasswordCredential{value: val, isSet: true} +} + +func (v NullablePasswordCredential) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePasswordCredential) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/schema/errors.go b/schema/errors/errors.go similarity index 99% rename from schema/errors.go rename to schema/errors/errors.go index cf91fdbcb7c6..e6f2f6f5364f 100644 --- a/schema/errors.go +++ b/schema/errors/errors.go @@ -1,4 +1,4 @@ -package schema +package errors import ( "fmt" diff --git a/selfservice/flow/login/error_test.go b/selfservice/flow/login/error_test.go index b8580e41825a..083328604e0e 100644 --- a/selfservice/flow/login/error_test.go +++ b/selfservice/flow/login/error_test.go @@ -3,6 +3,7 @@ package login_test import ( "context" "encoding/json" + "github.com/ory/kratos/schema/errors" "io/ioutil" "net/http" "testing" @@ -28,7 +29,6 @@ import ( "github.com/ory/kratos/driver/config" "github.com/ory/kratos/internal" "github.com/ory/kratos/internal/testhelpers" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/login" "github.com/ory/kratos/text" @@ -160,7 +160,7 @@ func TestHandleError(t *testing.T) { t.Cleanup(reset) loginFlow = newFlow(t, time.Minute, tc.t) - flowError = schema.NewInvalidCredentialsError() + flowError = errors.NewInvalidCredentialsError() ct = node.PasswordGroup res, err := ts.Client().Do(testhelpers.NewHTTPGetJSONRequest(t, ts.URL+"/error")) @@ -221,7 +221,7 @@ func TestHandleError(t *testing.T) { t.Cleanup(reset) loginFlow = newFlow(t, time.Minute, flow.TypeBrowser) - flowError = schema.NewInvalidCredentialsError() + flowError = errors.NewInvalidCredentialsError() ct = node.PasswordGroup lf, _ := expectLoginUI(t) diff --git a/selfservice/flow/login/handler.go b/selfservice/flow/login/handler.go index 1adbd1e9aa44..916e073065b1 100644 --- a/selfservice/flow/login/handler.go +++ b/selfservice/flow/login/handler.go @@ -1,6 +1,7 @@ package login import ( + errors2 "github.com/ory/kratos/schema/errors" "net/http" "time" @@ -13,7 +14,6 @@ import ( "github.com/ory/nosurf" "github.com/ory/kratos/identity" - "github.com/ory/kratos/schema" "github.com/ory/kratos/ui/node" "github.com/ory/x/decoderx" @@ -594,13 +594,13 @@ continueLogin: } if i == nil { - h.d.LoginFlowErrorHandler().WriteFlowError(w, r, f, node.DefaultGroup, errors.WithStack(schema.NewNoLoginStrategyResponsible())) + h.d.LoginFlowErrorHandler().WriteFlowError(w, r, f, node.DefaultGroup, errors.WithStack(errors2.NewNoLoginStrategyResponsible())) return } if err := h.d.LoginHookExecutor().PostLoginHook(w, r, f, i, sess); err != nil { if errors.Is(err, ErrAddressNotVerified) { - h.d.LoginFlowErrorHandler().WriteFlowError(w, r, f, node.DefaultGroup, errors.WithStack(schema.NewAddressNotVerifiedError())) + h.d.LoginFlowErrorHandler().WriteFlowError(w, r, f, node.DefaultGroup, errors.WithStack(errors2.NewAddressNotVerifiedError())) return } diff --git a/selfservice/flow/recovery/error_test.go b/selfservice/flow/recovery/error_test.go index 7ef7b2bc5f5f..7f230aedbf2b 100644 --- a/selfservice/flow/recovery/error_test.go +++ b/selfservice/flow/recovery/error_test.go @@ -2,6 +2,7 @@ package recovery_test import ( "context" + "github.com/ory/kratos/schema/errors" "io/ioutil" "net/http" "testing" @@ -27,7 +28,6 @@ import ( "github.com/ory/kratos/driver/config" "github.com/ory/kratos/internal" "github.com/ory/kratos/internal/testhelpers" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/recovery" "github.com/ory/kratos/text" @@ -145,7 +145,7 @@ func TestHandleError(t *testing.T) { t.Cleanup(reset) recoveryFlow = newFlow(t, time.Minute, tc.t) - flowError = schema.NewInvalidCredentialsError() + flowError = errors.NewInvalidCredentialsError() methodName = recovery.StrategyRecoveryLinkName res, err := ts.Client().Do(testhelpers.NewHTTPGetJSONRequest(t, ts.URL+"/error")) @@ -206,7 +206,7 @@ func TestHandleError(t *testing.T) { t.Cleanup(reset) recoveryFlow = newFlow(t, time.Minute, flow.TypeBrowser) - flowError = schema.NewInvalidCredentialsError() + flowError = errors.NewInvalidCredentialsError() methodName = node.RecoveryLinkGroup lf, _ := expectRecoveryUI(t) diff --git a/selfservice/flow/recovery/handler.go b/selfservice/flow/recovery/handler.go index de1032d1ba60..b7079dbbac36 100644 --- a/selfservice/flow/recovery/handler.go +++ b/selfservice/flow/recovery/handler.go @@ -1,13 +1,12 @@ package recovery import ( + errors2 "github.com/ory/kratos/schema/errors" "net/http" "time" "github.com/ory/nosurf" - "github.com/ory/kratos/schema" - "github.com/ory/kratos/ui/node" "github.com/ory/x/sqlcon" @@ -384,7 +383,7 @@ func (h *Handler) submitFlow(w http.ResponseWriter, r *http.Request, ps httprout } if !found { - h.d.RecoveryFlowErrorHandler().WriteFlowError(w, r, f, node.DefaultGroup, errors.WithStack(schema.NewNoRecoveryStrategyResponsible())) + h.d.RecoveryFlowErrorHandler().WriteFlowError(w, r, f, node.DefaultGroup, errors.WithStack(errors2.NewNoRecoveryStrategyResponsible())) return } diff --git a/selfservice/flow/registration/error_test.go b/selfservice/flow/registration/error_test.go index 6286868223ea..29518656348d 100644 --- a/selfservice/flow/registration/error_test.go +++ b/selfservice/flow/registration/error_test.go @@ -3,6 +3,7 @@ package registration_test import ( "context" "encoding/json" + "github.com/ory/kratos/schema/errors" "io/ioutil" "net/http" "testing" @@ -26,7 +27,6 @@ import ( "github.com/ory/kratos/driver/config" "github.com/ory/kratos/internal" "github.com/ory/kratos/internal/testhelpers" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/registration" "github.com/ory/kratos/text" @@ -146,7 +146,7 @@ func TestHandleError(t *testing.T) { t.Cleanup(reset) registrationFlow = newFlow(t, time.Minute, tc.t) - flowError = schema.NewInvalidCredentialsError() + flowError = errors.NewInvalidCredentialsError() group = node.PasswordGroup res, err := ts.Client().Do(testhelpers.NewHTTPGetJSONRequest(t, ts.URL+"/error")) @@ -207,7 +207,7 @@ func TestHandleError(t *testing.T) { t.Cleanup(reset) registrationFlow = newFlow(t, time.Minute, flow.TypeBrowser) - flowError = schema.NewInvalidCredentialsError() + flowError = errors.NewInvalidCredentialsError() group = node.PasswordGroup lf, _ := expectRegistrationUI(t) diff --git a/selfservice/flow/registration/handler.go b/selfservice/flow/registration/handler.go index 3d2991895c87..4f43272b760e 100644 --- a/selfservice/flow/registration/handler.go +++ b/selfservice/flow/registration/handler.go @@ -1,6 +1,7 @@ package registration import ( + errors2 "github.com/ory/kratos/schema/errors" "net/http" "time" @@ -8,8 +9,6 @@ import ( "github.com/ory/nosurf" - "github.com/ory/kratos/schema" - "github.com/ory/kratos/identity" "github.com/ory/kratos/ui/node" @@ -442,7 +441,7 @@ func (h *Handler) submitFlow(w http.ResponseWriter, r *http.Request, _ httproute } if s == nil { - h.d.RegistrationFlowErrorHandler().WriteFlowError(w, r, f, node.DefaultGroup, errors.WithStack(schema.NewNoRegistrationStrategyResponsible())) + h.d.RegistrationFlowErrorHandler().WriteFlowError(w, r, f, node.DefaultGroup, errors.WithStack(errors2.NewNoRegistrationStrategyResponsible())) return } diff --git a/selfservice/flow/registration/hook.go b/selfservice/flow/registration/hook.go index 72ea65336907..85c095b01c5c 100644 --- a/selfservice/flow/registration/hook.go +++ b/selfservice/flow/registration/hook.go @@ -3,6 +3,7 @@ package registration import ( "context" "fmt" + errors2 "github.com/ory/kratos/schema/errors" "net/http" "time" @@ -12,7 +13,6 @@ import ( "github.com/ory/kratos/driver/config" "github.com/ory/kratos/identity" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/session" "github.com/ory/kratos/x" @@ -120,7 +120,7 @@ func (e *HookExecutor) PostRegistrationHook(w http.ResponseWriter, r *http.Reque // would imply that the identity has to exist already. } else if err := e.d.IdentityManager().Create(r.Context(), i); err != nil { if errors.Is(err, sqlcon.ErrUniqueViolation) { - return schema.NewDuplicateCredentialsError() + return errors2.NewDuplicateCredentialsError() } return err } diff --git a/selfservice/flow/settings/error_test.go b/selfservice/flow/settings/error_test.go index dcb4e8156994..02a9079e6400 100644 --- a/selfservice/flow/settings/error_test.go +++ b/selfservice/flow/settings/error_test.go @@ -3,6 +3,7 @@ package settings_test import ( "context" "encoding/json" + errors2 "github.com/ory/kratos/schema/errors" "io/ioutil" "net/http" "testing" @@ -30,7 +31,6 @@ import ( "github.com/ory/kratos/identity" "github.com/ory/kratos/internal" "github.com/ory/kratos/internal/testhelpers" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/settings" "github.com/ory/kratos/session" @@ -166,7 +166,7 @@ func TestHandleError(t *testing.T) { t.Cleanup(reset) settingsFlow = newFlow(t, time.Minute, tc.t) - flowError = schema.NewInvalidCredentialsError() + flowError = errors2.NewInvalidCredentialsError() flowMethod = settings.StrategyProfile res, err := ts.Client().Do(testhelpers.NewHTTPGetJSONRequest(t, ts.URL+"/error")) @@ -343,7 +343,7 @@ func TestHandleError(t *testing.T) { t.Cleanup(reset) settingsFlow = newFlow(t, time.Minute, flow.TypeBrowser) - flowError = schema.NewInvalidCredentialsError() + flowError = errors2.NewInvalidCredentialsError() flowMethod = settings.StrategyProfile lf, _ := expectSettingsUI(t) @@ -360,7 +360,7 @@ func TestHandleError(t *testing.T) { id.SchemaURL = "http://some.random.url" settingsFlow = newFlow(t, time.Minute, flow.TypeBrowser) - flowError = schema.NewInvalidCredentialsError() + flowError = errors2.NewInvalidCredentialsError() flowMethod = settings.StrategyProfile lf, _ := expectSettingsUI(t) diff --git a/selfservice/flow/settings/handler.go b/selfservice/flow/settings/handler.go index dabfd3965018..56130609f38f 100644 --- a/selfservice/flow/settings/handler.go +++ b/selfservice/flow/settings/handler.go @@ -1,6 +1,7 @@ package settings import ( + errors2 "github.com/ory/kratos/schema/errors" "net/http" "time" @@ -533,7 +534,7 @@ func (h *Handler) submitSettingsFlow(w http.ResponseWriter, r *http.Request, ps if updateContext == nil { c := &UpdateContext{Session: ss, Flow: f} - h.d.SettingsFlowErrorHandler().WriteFlowError(w, r, node.DefaultGroup, f, c.GetIdentityToUpdate(), errors.WithStack(schema.NewNoSettingsStrategyResponsible())) + h.d.SettingsFlowErrorHandler().WriteFlowError(w, r, node.DefaultGroup, f, c.GetIdentityToUpdate(), errors.WithStack(errors2.NewNoSettingsStrategyResponsible())) return } diff --git a/selfservice/flow/settings/hook.go b/selfservice/flow/settings/hook.go index 5cc3fe4e3583..92de7057f6f8 100644 --- a/selfservice/flow/settings/hook.go +++ b/selfservice/flow/settings/hook.go @@ -3,13 +3,13 @@ package settings import ( "context" "fmt" + errors2 "github.com/ory/kratos/schema/errors" "net/http" "time" "github.com/ory/kratos/text" "github.com/ory/kratos/ui/node" - "github.com/ory/kratos/schema" "github.com/ory/x/sqlcon" "github.com/pkg/errors" @@ -153,7 +153,7 @@ func (e *HookExecutor) PostSettingsHook(w http.ResponseWriter, r *http.Request, return errors.WithStack(NewFlowNeedsReAuth()) } if errors.Is(err, sqlcon.ErrUniqueViolation) { - return schema.NewDuplicateCredentialsError() + return errors2.NewDuplicateCredentialsError() } return err } diff --git a/selfservice/flow/verification/error_test.go b/selfservice/flow/verification/error_test.go index 793f13b13f43..3440137dbb36 100644 --- a/selfservice/flow/verification/error_test.go +++ b/selfservice/flow/verification/error_test.go @@ -2,6 +2,7 @@ package verification_test import ( "context" + "github.com/ory/kratos/schema/errors" "io/ioutil" "net/http" "testing" @@ -27,7 +28,6 @@ import ( "github.com/ory/kratos/driver/config" "github.com/ory/kratos/internal" "github.com/ory/kratos/internal/testhelpers" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/verification" "github.com/ory/kratos/text" @@ -145,7 +145,7 @@ func TestHandleError(t *testing.T) { t.Cleanup(reset) verificationFlow = newFlow(t, time.Minute, tc.t) - flowError = schema.NewInvalidCredentialsError() + flowError = errors.NewInvalidCredentialsError() methodName = verification.StrategyVerificationLinkName res, err := ts.Client().Do(testhelpers.NewHTTPGetJSONRequest(t, ts.URL+"/error")) @@ -206,7 +206,7 @@ func TestHandleError(t *testing.T) { t.Cleanup(reset) verificationFlow = newFlow(t, time.Minute, flow.TypeBrowser) - flowError = schema.NewInvalidCredentialsError() + flowError = errors.NewInvalidCredentialsError() methodName = node.VerificationLinkGroup lf, _ := expectVerificationUI(t) diff --git a/selfservice/flow/verification/handler.go b/selfservice/flow/verification/handler.go index 3585f109daf8..14f11cd64e3b 100644 --- a/selfservice/flow/verification/handler.go +++ b/selfservice/flow/verification/handler.go @@ -1,12 +1,12 @@ package verification import ( + errors2 "github.com/ory/kratos/schema/errors" "net/http" "time" "github.com/ory/nosurf" - "github.com/ory/kratos/schema" "github.com/ory/kratos/ui/node" "github.com/ory/x/sqlcon" @@ -367,7 +367,7 @@ func (h *Handler) submitFlow(w http.ResponseWriter, r *http.Request, ps httprout } if !found { - h.d.VerificationFlowErrorHandler().WriteFlowError(w, r, f, node.DefaultGroup, errors.WithStack(schema.NewNoVerificationStrategyResponsible())) + h.d.VerificationFlowErrorHandler().WriteFlowError(w, r, f, node.DefaultGroup, errors.WithStack(errors2.NewNoVerificationStrategyResponsible())) return } diff --git a/selfservice/strategy/link/strategy_recovery.go b/selfservice/strategy/link/strategy_recovery.go index 343070d403bb..e0b0c970b5c4 100644 --- a/selfservice/strategy/link/strategy_recovery.go +++ b/selfservice/strategy/link/strategy_recovery.go @@ -1,6 +1,7 @@ package link import ( + errors2 "github.com/ory/kratos/schema/errors" "net/http" "net/url" "time" @@ -11,7 +12,6 @@ import ( "github.com/ory/herodot" "github.com/ory/kratos/identity" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/recovery" "github.com/ory/kratos/selfservice/strategy" @@ -392,7 +392,7 @@ func (s *Strategy) recoveryHandleFormSubmission(w http.ResponseWriter, r *http.R } if len(body.Email) == 0 { - return s.HandleRecoveryError(w, r, f, body, schema.NewRequiredError("#/email", "email")) + return s.HandleRecoveryError(w, r, f, body, errors2.NewRequiredError("#/email", "email")) } if err := flow.EnsureCSRF(s.d, r, f.Type, s.d.Config(r.Context()).DisableAPIFlowEnforcement(), s.d.GenerateCSRFToken, body.CSRFToken); err != nil { diff --git a/selfservice/strategy/link/strategy_verification.go b/selfservice/strategy/link/strategy_verification.go index 959d1af2d97a..a7364a12ed33 100644 --- a/selfservice/strategy/link/strategy_verification.go +++ b/selfservice/strategy/link/strategy_verification.go @@ -1,6 +1,7 @@ package link import ( + errors2 "github.com/ory/kratos/schema/errors" "net/http" "net/url" "time" @@ -8,7 +9,6 @@ import ( "github.com/pkg/errors" "github.com/ory/kratos/identity" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/verification" "github.com/ory/kratos/text" @@ -149,7 +149,7 @@ func (s *Strategy) verificationHandleFormSubmission(w http.ResponseWriter, r *ht } if len(body.Email) == 0 { - return s.handleVerificationError(w, r, f, body, schema.NewRequiredError("#/email", "email")) + return s.handleVerificationError(w, r, f, body, errors2.NewRequiredError("#/email", "email")) } if err := flow.EnsureCSRF(s.d, r, f.Type, s.d.Config(r.Context()).DisableAPIFlowEnforcement(), s.d.GenerateCSRFToken, body.CSRFToken); err != nil { diff --git a/selfservice/strategy/lookup/login.go b/selfservice/strategy/lookup/login.go index c4ef436bb7ff..c9efe5321144 100644 --- a/selfservice/strategy/lookup/login.go +++ b/selfservice/strategy/lookup/login.go @@ -2,6 +2,7 @@ package lookup import ( "encoding/json" + errors2 "github.com/ory/kratos/schema/errors" "net/http" "time" @@ -13,7 +14,6 @@ import ( "github.com/ory/herodot" "github.com/ory/kratos/identity" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/login" "github.com/ory/kratos/session" @@ -108,7 +108,7 @@ func (s *Strategy) Login(w http.ResponseWriter, r *http.Request, f *login.Flow, i, c, err := s.d.PrivilegedIdentityPool().FindByCredentialsIdentifier(r.Context(), s.ID(), ss.IdentityID.String()) if errors.Is(err, sqlcon.ErrNoRows) { - return nil, s.handleLoginError(r, f, errors.WithStack(schema.NewNoLookupDefined())) + return nil, s.handleLoginError(r, f, errors.WithStack(errors2.NewNoLookupDefined())) } else if err != nil { return nil, s.handleLoginError(r, f, err) } @@ -125,13 +125,13 @@ func (s *Strategy) Login(w http.ResponseWriter, r *http.Request, f *login.Flow, o.RecoveryCodes[k].UsedAt = sqlxx.NullTime(time.Now().UTC().Round(time.Second)) found = true } else { - return nil, s.handleLoginError(r, f, errors.WithStack(schema.NewLookupAlreadyUsed())) + return nil, s.handleLoginError(r, f, errors.WithStack(errors2.NewLookupAlreadyUsed())) } } } if !found { - return nil, s.handleLoginError(r, f, errors.WithStack(schema.NewErrorValidationLookupInvalid())) + return nil, s.handleLoginError(r, f, errors.WithStack(errors2.NewErrorValidationLookupInvalid())) } toUpdate, err := s.d.PrivilegedIdentityPool().GetIdentityConfidential(r.Context(), ss.IdentityID) diff --git a/selfservice/strategy/lookup/strategy.go b/selfservice/strategy/lookup/strategy.go index 8412d5421560..4c0870f0fe5b 100644 --- a/selfservice/strategy/lookup/strategy.go +++ b/selfservice/strategy/lookup/strategy.go @@ -34,7 +34,7 @@ type registrationStrategyDependencies interface { continuity.ManagementProvider errorx.ManagementProvider - hash.HashProvider + hash.Generator registration.HandlerProvider registration.HooksProvider diff --git a/selfservice/strategy/password/login.go b/selfservice/strategy/password/login.go index 641b3fec182a..d0a704735e84 100644 --- a/selfservice/strategy/password/login.go +++ b/selfservice/strategy/password/login.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + errors2 "github.com/ory/kratos/schema/errors" "net/http" "time" @@ -18,7 +19,6 @@ import ( "github.com/ory/kratos/hash" "github.com/ory/kratos/identity" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/login" "github.com/ory/kratos/text" @@ -65,17 +65,17 @@ func (s *Strategy) Login(w http.ResponseWriter, r *http.Request, f *login.Flow, i, c, err := s.d.PrivilegedIdentityPool().FindByCredentialsIdentifier(r.Context(), s.ID(), p.Identifier) if err != nil { time.Sleep(x.RandomDelay(s.d.Config(r.Context()).HasherArgon2().ExpectedDuration, s.d.Config(r.Context()).HasherArgon2().ExpectedDeviation)) - return nil, s.handleLoginError(w, r, f, &p, errors.WithStack(schema.NewInvalidCredentialsError())) + return nil, s.handleLoginError(w, r, f, &p, errors.WithStack(errors2.NewInvalidCredentialsError())) } - var o CredentialsConfig + var o identity.CredentialsConfig d := json.NewDecoder(bytes.NewBuffer(c.Config)) if err := d.Decode(&o); err != nil { return nil, herodot.ErrInternalServerError.WithReason("The password credentials could not be decoded properly").WithDebug(err.Error()).WithWrap(err) } if err := hash.Compare(r.Context(), []byte(p.Password), []byte(o.HashedPassword)); err != nil { - return nil, s.handleLoginError(w, r, f, &p, errors.WithStack(schema.NewInvalidCredentialsError())) + return nil, s.handleLoginError(w, r, f, &p, errors.WithStack(errors2.NewInvalidCredentialsError())) } if !s.d.Hasher().Understands([]byte(o.HashedPassword)) { @@ -101,7 +101,7 @@ func (s *Strategy) migratePasswordHash(ctx context.Context, identifier uuid.UUID if err != nil { return err } - co, err := json.Marshal(&CredentialsConfig{HashedPassword: string(hpw)}) + co, err := json.Marshal(&identity.CredentialsConfig{HashedPassword: string(hpw)}) if err != nil { return errors.Wrap(err, "unable to encode password configuration to JSON") } diff --git a/selfservice/strategy/password/login_test.go b/selfservice/strategy/password/login_test.go index 8475175a68d6..6f73ab10ae4b 100644 --- a/selfservice/strategy/password/login_test.go +++ b/selfservice/strategy/password/login_test.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/ory/kratos/schema/errors" "io/ioutil" "net/http" "net/url" @@ -35,7 +36,6 @@ import ( "github.com/ory/kratos/identity" "github.com/ory/kratos/internal" "github.com/ory/kratos/internal/testhelpers" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow/login" "github.com/ory/kratos/text" "github.com/ory/kratos/x" @@ -427,7 +427,7 @@ func TestCompleteLogin(t *testing.T) { ensureFieldsExist(t, []byte(body)) assert.Equal(t, - errorsx.Cause(schema.NewInvalidCredentialsError()).(*schema.ValidationError).Messages[0].Text, + errorsx.Cause(errors.NewInvalidCredentialsError()).(*errors.ValidationError).Messages[0].Text, gjson.Get(body, "ui.messages.0.text").String(), "%s", body, ) @@ -697,7 +697,7 @@ func TestCompleteLogin(t *testing.T) { ensureFieldsExist(t, []byte(body)) assert.Equal(t, - errorsx.Cause(schema.NewAddressNotVerifiedError()).(*schema.ValidationError).Messages[0].Text, + errorsx.Cause(errors.NewAddressNotVerifiedError()).(*errors.ValidationError).Messages[0].Text, gjson.Get(body, "ui.messages.0.text").String(), "%s", body, ) diff --git a/selfservice/strategy/password/registration.go b/selfservice/strategy/password/registration.go index 7c09e0309064..56312a75dcc8 100644 --- a/selfservice/strategy/password/registration.go +++ b/selfservice/strategy/password/registration.go @@ -3,6 +3,7 @@ package password import ( "context" "encoding/json" + errors2 "github.com/ory/kratos/schema/errors" "net/http" "github.com/ory/kratos/text" @@ -12,7 +13,6 @@ import ( "github.com/ory/herodot" "github.com/ory/kratos/identity" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/registration" "github.com/ory/kratos/ui/container" @@ -98,7 +98,7 @@ func (s *Strategy) Register(w http.ResponseWriter, r *http.Request, f *registrat } if len(p.Password) == 0 { - return s.handleRegistrationError(w, r, f, &p, schema.NewRequiredError("#/password", "password")) + return s.handleRegistrationError(w, r, f, &p, errors2.NewRequiredError("#/password", "password")) } if len(p.Traits) == 0 { @@ -110,7 +110,8 @@ func (s *Strategy) Register(w http.ResponseWriter, r *http.Request, f *registrat return s.handleRegistrationError(w, r, f, &p, err) } - co, err := json.Marshal(&CredentialsConfig{HashedPassword: string(hpw)}) + // CJC Aqui hace el hash + co, err := json.Marshal(&identity.CredentialsConfig{HashedPassword: string(hpw)}) if err != nil { return s.handleRegistrationError(w, r, f, &p, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("Unable to encode password options to JSON: %s", err))) } @@ -135,7 +136,7 @@ func (s *Strategy) validateCredentials(ctx context.Context, i *identity.Identity // This should never happen return errors.WithStack(x.PseudoPanic.WithReasonf("identity object did not provide the %s CredentialType unexpectedly", identity.CredentialsTypePassword)) } else if len(c.Identifiers) == 0 { - return schema.NewMissingIdentifierError() + return errors2.NewMissingIdentifierError() } for _, id := range c.Identifiers { @@ -143,7 +144,7 @@ func (s *Strategy) validateCredentials(ctx context.Context, i *identity.Identity if _, ok := errorsx.Cause(err).(*herodot.DefaultError); ok { return err } - return schema.NewPasswordPolicyViolationError("#/password", err.Error()) + return errors2.NewPasswordPolicyViolationError("#/password", err.Error()) } } diff --git a/selfservice/strategy/password/settings.go b/selfservice/strategy/password/settings.go index 45d6aa60d4db..48c91e905b86 100644 --- a/selfservice/strategy/password/settings.go +++ b/selfservice/strategy/password/settings.go @@ -2,6 +2,7 @@ package password import ( "encoding/json" + errors2 "github.com/ory/kratos/schema/errors" "net/http" "time" @@ -16,7 +17,6 @@ import ( "github.com/ory/herodot" "github.com/ory/kratos/identity" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/settings" "github.com/ory/kratos/x" @@ -116,7 +116,7 @@ func (s *Strategy) continueSettingsFlow( } if len(p.Password) == 0 { - return schema.NewRequiredError("#/password", "password") + return errors2.NewRequiredError("#/password", "password") } hpw, err := s.d.Hasher().Generate(r.Context(), []byte(p.Password)) @@ -124,7 +124,7 @@ func (s *Strategy) continueSettingsFlow( return err } - co, err := json.Marshal(&CredentialsConfig{HashedPassword: string(hpw)}) + co, err := json.Marshal(&identity.CredentialsConfig{HashedPassword: string(hpw)}) if err != nil { return errors.WithStack(herodot.ErrInternalServerError.WithReasonf("Unable to encode password options to JSON: %s", err)) } diff --git a/selfservice/strategy/password/strategy.go b/selfservice/strategy/password/strategy.go index 2b5f2211ee63..5dd8ba7ee804 100644 --- a/selfservice/strategy/password/strategy.go +++ b/selfservice/strategy/password/strategy.go @@ -38,7 +38,7 @@ type registrationStrategyDependencies interface { errorx.ManagementProvider ValidationProvider - hash.HashProvider + hash.Generator registration.HandlerProvider registration.HooksProvider @@ -81,7 +81,7 @@ func NewStrategy(d registrationStrategyDependencies) *Strategy { func (s *Strategy) CountActiveCredentials(cc map[identity.CredentialsType]identity.Credentials) (count int, err error) { for _, c := range cc { if c.Type == s.ID() && len(c.Config) > 0 { - var conf CredentialsConfig + var conf identity.CredentialsConfig if err = json.Unmarshal(c.Config, &conf); err != nil { return 0, errors.WithStack(err) } diff --git a/selfservice/strategy/password/types.go b/selfservice/strategy/password/types.go index e8d8d924310c..82c1b9650b07 100644 --- a/selfservice/strategy/password/types.go +++ b/selfservice/strategy/password/types.go @@ -5,10 +5,10 @@ import ( ) // CredentialsConfig is the struct that is being used as part of the identity credentials. -type CredentialsConfig struct { - // HashedPassword is a hash-representation of the password. - HashedPassword string `json:"hashed_password"` -} +//type CredentialsConfig struct { +// // HashedPassword is a hash-representation of the password. +// HashedPassword string `json:"hashed_password"` +//} // submitSelfServiceLoginFlowWithPasswordMethodBody is used to decode the login form payload. // diff --git a/selfservice/strategy/totp/login.go b/selfservice/strategy/totp/login.go index a3eb8747ac39..029e1db83e39 100644 --- a/selfservice/strategy/totp/login.go +++ b/selfservice/strategy/totp/login.go @@ -2,6 +2,7 @@ package totp import ( "encoding/json" + errors2 "github.com/ory/kratos/schema/errors" "net/http" "github.com/pkg/errors" @@ -10,7 +11,6 @@ import ( "github.com/ory/herodot" "github.com/ory/kratos/identity" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/login" "github.com/ory/kratos/session" @@ -105,7 +105,7 @@ func (s *Strategy) Login(w http.ResponseWriter, r *http.Request, f *login.Flow, i, c, err := s.d.PrivilegedIdentityPool().FindByCredentialsIdentifier(r.Context(), s.ID(), ss.IdentityID.String()) if err != nil { - return nil, s.handleLoginError(r, f, errors.WithStack(schema.NewNoTOTPDeviceRegistered())) + return nil, s.handleLoginError(r, f, errors.WithStack(errors2.NewNoTOTPDeviceRegistered())) } var o CredentialsConfig @@ -119,7 +119,7 @@ func (s *Strategy) Login(w http.ResponseWriter, r *http.Request, f *login.Flow, } if !totp.Validate(p.TOTPCode, key.Secret()) { - return nil, s.handleLoginError(r, f, errors.WithStack(schema.NewTOTPVerifierWrongError("#/"))) + return nil, s.handleLoginError(r, f, errors.WithStack(errors2.NewTOTPVerifierWrongError("#/"))) } f.Active = s.ID() diff --git a/selfservice/strategy/totp/settings.go b/selfservice/strategy/totp/settings.go index 56bff7759c32..381c3ea78132 100644 --- a/selfservice/strategy/totp/settings.go +++ b/selfservice/strategy/totp/settings.go @@ -3,6 +3,7 @@ package totp import ( "context" "encoding/json" + errors2 "github.com/ory/kratos/schema/errors" "net/http" "time" @@ -12,8 +13,6 @@ import ( "github.com/tidwall/sjson" "github.com/ory/herodot" - "github.com/ory/kratos/schema" - "github.com/ory/kratos/text" "github.com/ory/kratos/ui/node" @@ -174,11 +173,11 @@ func (s *Strategy) continueSettingsFlowAddTOTP(w http.ResponseWriter, r *http.Re } if p.ValidationTOTP == "" { - return nil, schema.NewRequiredError("#/totp_code", "totp_code") + return nil, errors2.NewRequiredError("#/totp_code", "totp_code") } if !totp.Validate(p.ValidationTOTP, key.Secret()) { - return nil, schema.NewTOTPVerifierWrongError("#/totp_code") + return nil, errors2.NewTOTPVerifierWrongError("#/totp_code") } co, err := json.Marshal(&CredentialsConfig{TOTPURL: key.URL()}) diff --git a/selfservice/strategy/totp/strategy.go b/selfservice/strategy/totp/strategy.go index 35ed16f41d49..ee75535b1cad 100644 --- a/selfservice/strategy/totp/strategy.go +++ b/selfservice/strategy/totp/strategy.go @@ -35,7 +35,7 @@ type registrationStrategyDependencies interface { continuity.ManagementProvider errorx.ManagementProvider - hash.HashProvider + hash.Generator registration.HandlerProvider registration.HooksProvider diff --git a/selfservice/strategy/webauthn/login.go b/selfservice/strategy/webauthn/login.go index 73e5384f3cda..bdc88ebea46d 100644 --- a/selfservice/strategy/webauthn/login.go +++ b/selfservice/strategy/webauthn/login.go @@ -2,6 +2,7 @@ package webauthn import ( "encoding/json" + errors2 "github.com/ory/kratos/schema/errors" "net/http" "strings" @@ -16,7 +17,6 @@ import ( "github.com/ory/herodot" "github.com/ory/kratos/identity" - "github.com/ory/kratos/schema" "github.com/ory/kratos/selfservice/flow" "github.com/ory/kratos/selfservice/flow/login" "github.com/ory/kratos/session" @@ -147,7 +147,7 @@ func (s *Strategy) Login(w http.ResponseWriter, r *http.Request, f *login.Flow, i, c, err := s.d.PrivilegedIdentityPool().FindByCredentialsIdentifier(r.Context(), s.ID(), ss.IdentityID.String()) if err != nil { - return nil, s.handleLoginError(r, f, errors.WithStack(schema.NewNoWebAuthnRegistered())) + return nil, s.handleLoginError(r, f, errors.WithStack(errors2.NewNoWebAuthnRegistered())) } var o CredentialsConfig @@ -171,7 +171,7 @@ func (s *Strategy) Login(w http.ResponseWriter, r *http.Request, f *login.Flow, } if _, err := web.ValidateLogin(&wrappedUser{id: i.ID, c: o.Credentials.ToWebAuthn()}, webAuthnSess, webAuthnResponse); err != nil { - return nil, s.handleLoginError(r, f, errors.WithStack(schema.NewWebAuthnVerifierWrongError("#/"))) + return nil, s.handleLoginError(r, f, errors.WithStack(errors2.NewWebAuthnVerifierWrongError("#/"))) } // Remove the WebAuthn URL from the internal context now that it is set! diff --git a/selfservice/strategy/webauthn/strategy.go b/selfservice/strategy/webauthn/strategy.go index bfec17a541aa..0e605906bc19 100644 --- a/selfservice/strategy/webauthn/strategy.go +++ b/selfservice/strategy/webauthn/strategy.go @@ -37,7 +37,7 @@ type registrationStrategyDependencies interface { continuity.ManagementProvider errorx.ManagementProvider - hash.HashProvider + hash.Generator registration.HandlerProvider registration.HooksProvider diff --git a/spec/api.json b/spec/api.json index 4a0a17f61125..677fcb1fef61 100755 --- a/spec/api.json +++ b/spec/api.json @@ -77,6 +77,9 @@ }, "adminCreateIdentityBody": { "properties": { + "password": { + "$ref": "#/components/schemas/passwordCredential" + }, "schema_id": { "description": "SchemaID is the ID of the JSON Schema to be used for validating the identity's traits.", "type": "string" @@ -87,6 +90,13 @@ "traits": { "description": "Traits represent an identity's traits. The identity is able to create, modify, and delete traits\nin a self-service manner. The input will always be validated against the JSON Schema defined\nin `schema_url`.", "type": "object" + }, + "verifiable_addresses": { + "description": "VerifiableAddresses contains all the addresses that can be verified by the user.", + "items": { + "$ref": "#/components/schemas/verifiableIdentityAddress" + }, + "type": "array" } }, "required": [ @@ -471,6 +481,25 @@ "title": "NullTime implements sql.NullTime functionality.", "type": "string" }, + "passwordCredential": { + "description": "The password of the user. It represents a cleartext or hashed user password.", + "properties": { + "is_hashed": { + "description": "This field must be true if the value represents a hashed password. Otherwise the value is assumed to be a\ncleartext password and it will be hashed before storing.", + "type": "boolean" + }, + "value": { + "description": "Value represents the value of the password in clear text or hashed", + "type": "string" + } + }, + "required": [ + "value", + "is_hashed" + ], + "title": "User's password", + "type": "object" + }, "selfServiceBrowserLocationChangeRequiredError": { "properties": { "code": { @@ -2110,7 +2139,7 @@ ] }, "post": { - "description": "This endpoint creates an identity. It is NOT possible to set an identity's credentials (password, ...)\nusing this method! A way to achieve that will be introduced in the future.\n\nLearn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model).", + "description": "This endpoint creates an identity. Optionally a password can be set for the newly created identity. Do to so\na password field must be included on the creation request. The password field can be in cleartext or hashed with\nany of the supported hashing algorithms. Using already hashed values can be useful when moving from another user\nauthentication mechanism to Kratos.\nLearn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model).", "operationId": "adminCreateIdentity", "requestBody": { "content": { diff --git a/spec/swagger.json b/spec/swagger.json index 3e3d79fad90c..04b2ab2ff79b 100755 --- a/spec/swagger.json +++ b/spec/swagger.json @@ -159,7 +159,7 @@ "oryAccessToken": [] } ], - "description": "This endpoint creates an identity. It is NOT possible to set an identity's credentials (password, ...)\nusing this method! A way to achieve that will be introduced in the future.\n\nLearn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model).", + "description": "This endpoint creates an identity. Optionally a password can be set for the newly created identity. Do to so\na password field must be included on the creation request. The password field can be in cleartext or hashed with\nany of the supported hashing algorithms. Using already hashed values can be useful when moving from another user\nauthentication mechanism to Kratos.\nLearn how identities work in [Ory Kratos' User And Identity Model Documentation](https://www.ory.sh/docs/next/kratos/concepts/identity-user-model).", "consumes": [ "application/json" ], @@ -2067,6 +2067,9 @@ "traits" ], "properties": { + "password": { + "$ref": "#/definitions/passwordCredential" + }, "schema_id": { "description": "SchemaID is the ID of the JSON Schema to be used for validating the identity's traits.", "type": "string" @@ -2077,6 +2080,13 @@ "traits": { "description": "Traits represent an identity's traits. The identity is able to create, modify, and delete traits\nin a self-service manner. The input will always be validated against the JSON Schema defined\nin `schema_url`.", "type": "object" + }, + "verifiable_addresses": { + "description": "VerifiableAddresses contains all the addresses that can be verified by the user.", + "type": "array", + "items": { + "$ref": "#/definitions/verifiableIdentityAddress" + } } } }, @@ -2442,6 +2452,25 @@ "format": "date-time", "title": "NullTime implements sql.NullTime functionality." }, + "passwordCredential": { + "description": "The password of the user. It represents a cleartext or hashed user password.", + "type": "object", + "title": "User's password", + "required": [ + "value", + "is_hashed" + ], + "properties": { + "is_hashed": { + "description": "This field must be true if the value represents a hashed password. Otherwise the value is assumed to be a\ncleartext password and it will be hashed before storing.", + "type": "boolean" + }, + "value": { + "description": "Value represents the value of the password in clear text or hashed", + "type": "string" + } + } + }, "selfServiceBrowserLocationChangeRequiredError": { "type": "object", "title": "Is sent when a flow requires a browser to change its location.", diff --git a/ui/container/container.go b/ui/container/container.go index 0602b595fd5c..522c38c7321a 100644 --- a/ui/container/container.go +++ b/ui/container/container.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + errors2 "github.com/ory/kratos/schema/errors" "net/http" "strings" @@ -18,7 +19,6 @@ import ( "github.com/ory/x/jsonx" "github.com/ory/x/stringslice" - "github.com/ory/kratos/schema" "github.com/ory/kratos/text" ) @@ -156,7 +156,7 @@ func (c *Container) ParseError(group node.Group, err error) error { return nil } return err - } else if e := new(schema.ValidationError); errors.As(err, &e) { + } else if e := new(errors2.ValidationError); errors.As(err, &e) { pointer, _ := jsonschemax.JSONPointerToDotNotation(e.InstancePtr) for i := range e.Messages { c.AddMessage(group, &e.Messages[i], pointer) diff --git a/ui/container/container_test.go b/ui/container/container_test.go index 6cc733733b2f..e58e1d945426 100644 --- a/ui/container/container_test.go +++ b/ui/container/container_test.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + errors2 "github.com/ory/kratos/schema/errors" "net/http" "net/url" "sort" @@ -21,7 +22,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/ory/kratos/schema" "github.com/ory/kratos/text" ) @@ -214,7 +214,7 @@ func TestContainer(t *testing.T) { {err: errors.New("foo"), expectErr: true}, {err: &herodot.ErrNotFound, expectErr: true}, {err: herodot.ErrBadRequest.WithReason("tests"), expect: Container{Nodes: node.Nodes{}, Messages: text.Messages{*text.NewValidationErrorGeneric("tests")}}}, - {err: schema.NewInvalidCredentialsError(), expect: Container{Nodes: node.Nodes{}, Messages: text.Messages{*text.NewErrorValidationInvalidCredentials()}}}, + {err: errors2.NewInvalidCredentialsError(), expect: Container{Nodes: node.Nodes{}, Messages: text.Messages{*text.NewErrorValidationInvalidCredentials()}}}, {err: &jsonschema.ValidationError{Message: "test", InstancePtr: "#/foo/bar/baz"}, expect: Container{Nodes: node.Nodes{ &node.Node{Group: node.DefaultGroup, Type: node.Input, Attributes: &node.InputAttributes{Name: "foo.bar.baz", Type: node.InputAttributeTypeText}, Messages: text.Messages{*text.NewValidationErrorGeneric("test")}, Meta: new(node.Meta)}, }}},