Skip to content

Commit

Permalink
Merge pull request #109 from Wikia/revert-107-revert-106-PLATFORM-8994
Browse files Browse the repository at this point in the history
Revert 107 revert 106 platform 8994
  • Loading branch information
abador authored Mar 6, 2024
2 parents ba9b4a1 + f797c8c commit 94e23d3
Show file tree
Hide file tree
Showing 25 changed files with 78 additions and 5 deletions.
7 changes: 7 additions & 0 deletions .schemastore/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1564,6 +1564,13 @@
"default": 8,
"minimum": 6
},
"max_password_length": {
"title": "Maximum Password Length",
"description": "Defines the maximum length of the password.",
"type": "integer",
"default": 1024,
"minimum": 20
},
"identifier_similarity_check_enabled": {
"title": "Enable password-identifier similarity check",
"description": "If set to false the password validation does not check for similarity between the password and the user identifier.",
Expand Down
3 changes: 3 additions & 0 deletions driver/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ const (
ViperKeyPasswordHaveIBeenPwnedEnabled = "selfservice.methods.password.config.haveibeenpwned_enabled"
ViperKeyPasswordMaxBreaches = "selfservice.methods.password.config.max_breaches"
ViperKeyPasswordMinLength = "selfservice.methods.password.config.min_password_length"
ViperKeyPasswordMaxLength = "selfservice.methods.password.config.max_password_length"
ViperKeyPasswordIdentifierSimilarityCheckEnabled = "selfservice.methods.password.config.identifier_similarity_check_enabled"
ViperKeyIgnoreNetworkErrors = "selfservice.methods.password.config.ignore_network_errors"
ViperKeyTOTPIssuer = "selfservice.methods.totp.config.issuer"
Expand Down Expand Up @@ -260,6 +261,7 @@ type (
MaxBreaches uint `json:"max_breaches"`
IgnoreNetworkErrors bool `json:"ignore_network_errors"`
MinPasswordLength uint `json:"min_password_length"`
MaxPasswordLength uint `json:"max_password_length"`
IdentifierSimilarityCheckEnabled bool `json:"identifier_similarity_check_enabled"`
}
Schemas []Schema
Expand Down Expand Up @@ -1415,6 +1417,7 @@ func (p *Config) PasswordPolicyConfig(ctx context.Context) *PasswordPolicy {
MaxBreaches: uint(p.GetProvider(ctx).Int(ViperKeyPasswordMaxBreaches)),
IgnoreNetworkErrors: p.GetProvider(ctx).BoolF(ViperKeyIgnoreNetworkErrors, true),
MinPasswordLength: uint(p.GetProvider(ctx).IntF(ViperKeyPasswordMinLength, 8)),
MaxPasswordLength: uint(p.GetProvider(ctx).IntF(ViperKeyPasswordMaxLength, 20)),
IdentifierSimilarityCheckEnabled: p.GetProvider(ctx).BoolF(ViperKeyPasswordIdentifierSimilarityCheckEnabled, true),
}
}
Expand Down
2 changes: 1 addition & 1 deletion driver/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ func TestViperProvider(t *testing.T) {
config string
enabled bool
}{
{id: "password", enabled: true, config: `{"haveibeenpwned_host":"api.pwnedpasswords.com","haveibeenpwned_enabled":true,"ignore_network_errors":true,"max_breaches":0,"min_password_length":8,"identifier_similarity_check_enabled":true}`},
{id: "password", enabled: true, config: `{"haveibeenpwned_host":"api.pwnedpasswords.com","haveibeenpwned_enabled":true,"ignore_network_errors":true,"max_breaches":0,"min_password_length":8,"max_password_length":1024,"identifier_similarity_check_enabled":true}`},
{id: "oidc", enabled: true, config: `{"providers":[{"client_id":"a","client_secret":"b","id":"github","provider":"github","mapper_url":"http://test.kratos.ory.sh/default-identity.schema.json"}]}`},
{id: "totp", enabled: true, config: `{"issuer":"issuer.ory.sh"}`},
} {
Expand Down
7 changes: 7 additions & 0 deletions embedx/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1564,6 +1564,13 @@
"default": 8,
"minimum": 6
},
"max_password_length": {
"title": "Maximum Password Length",
"description": "Defines the maximum length of the password.",
"type": "integer",
"default": 1024,
"minimum": 20
},
"identifier_similarity_check_enabled": {
"title": "Enable password-identifier similarity check",
"description": "If set to false the password validation does not check for similarity between the password and the user identifier.",
Expand Down
4 changes: 4 additions & 0 deletions internal/client-go/model_ui_node_input_attributes.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions internal/httpclient/model_ui_node_input_attributes.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
"type": "password",
"required": true,
"autocomplete": "new-password",
"minlength": 8,
"maxlength": 1024,
"disabled": false,
"node_type": "input"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
"type": "password",
"required": true,
"autocomplete": "new-password",
"minlength": 8,
"maxlength": 1024,
"disabled": false,
"node_type": "input"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
"type": "password",
"required": true,
"autocomplete": "new-password",
"minlength": 8,
"maxlength": 1024,
"disabled": false,
"node_type": "input"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
"type": "password",
"required": true,
"autocomplete": "new-password",
"minlength": 8,
"maxlength": 1024,
"disabled": false,
"node_type": "input"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
"type": "password",
"required": true,
"autocomplete": "new-password",
"minlength": 8,
"maxlength": 1024,
"disabled": false,
"node_type": "input"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
"type": "password",
"required": true,
"autocomplete": "new-password",
"minlength": 8,
"maxlength": 1024,
"disabled": false,
"node_type": "input"
},
Expand Down
8 changes: 7 additions & 1 deletion selfservice/strategy/password/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ func (s *Strategy) Login(w http.ResponseWriter, r *http.Request, f *login.Flow,
return nil, s.handleLoginError(w, r, f, &p, err)
}

// Reduce possibility of DDoS attacks with long password
if len([]byte(p.Password)) > int(s.d.Config().PasswordPolicyConfig(r.Context()).MaxPasswordLength) {
time.Sleep(x.RandomDelay(s.d.Config().HasherArgon2(r.Context()).ExpectedDuration, s.d.Config().HasherArgon2(r.Context()).ExpectedDeviation))
return nil, s.handleLoginError(w, r, f, &p, errors.WithStack(schema.NewInvalidCredentialsError()))
}

i, c, err := s.d.PrivilegedIdentityPool().FindByCredentialsIdentifier(r.Context(), s.ID(), stringsx.Coalesce(p.Identifier, p.LegacyIdentifier))
if err != nil {
time.Sleep(x.RandomDelay(s.d.Config().HasherArgon2(r.Context()).ExpectedDuration, s.d.Config().HasherArgon2(r.Context()).ExpectedDeviation))
Expand Down Expand Up @@ -152,7 +158,7 @@ func (s *Strategy) PopulateLoginMethod(r *http.Request, requestedAAL identity.Au
}

sr.UI.SetCSRF(s.d.GenerateCSRFToken(r))
sr.UI.SetNode(NewPasswordNode("password", node.InputAttributeAutocompleteCurrentPassword))
sr.UI.SetNode(NewPasswordNode("password", node.InputAttributeAutocompleteCurrentPassword, s.d.Config().PasswordPolicyConfig(r.Context())))
sr.UI.GetNodes().Append(node.NewInputField("method", "password", node.PasswordGroup, node.InputAttributeTypeSubmit).WithMetaLabel(text.NewInfoLogin()))

return nil
Expand Down
5 changes: 4 additions & 1 deletion selfservice/strategy/password/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
package password

import (
"github.com/ory/kratos/driver/config"
"github.com/ory/kratos/text"
"github.com/ory/kratos/ui/node"
)

func NewPasswordNode(name string, autocomplete node.UiNodeInputAttributeAutocomplete) *node.Node {
func NewPasswordNode(name string, autocomplete node.UiNodeInputAttributeAutocomplete, passwordPolicy *config.PasswordPolicy) *node.Node {
return node.NewInputField(name, nil, node.PasswordGroup,
node.InputAttributeTypePassword,
node.WithRequiredInputAttribute,
node.WithInputAttributes(func(a *node.InputAttributes) {
a.MinLength = passwordPolicy.MinPasswordLength
a.MaxLength = passwordPolicy.MaxPasswordLength
a.Autocomplete = autocomplete
})).
WithMetaLabel(text.NewInfoNodeInputPassword())
Expand Down
2 changes: 1 addition & 1 deletion selfservice/strategy/password/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func (s *Strategy) PopulateRegistrationMethod(r *http.Request, f *registration.F
}

f.UI.SetCSRF(s.d.GenerateCSRFToken(r))
f.UI.Nodes.Upsert(NewPasswordNode("password", node.InputAttributeAutocompleteNewPassword))
f.UI.Nodes.Upsert(NewPasswordNode("password", node.InputAttributeAutocompleteNewPassword, s.d.Config().PasswordPolicyConfig(r.Context())))
f.UI.Nodes.Append(node.NewInputField("method", "password", node.PasswordGroup, node.InputAttributeTypeSubmit).WithMetaLabel(text.NewInfoRegistration()))

return nil
Expand Down
2 changes: 1 addition & 1 deletion selfservice/strategy/password/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func (s *Strategy) continueSettingsFlow(

func (s *Strategy) PopulateSettingsMethod(r *http.Request, _ *identity.Identity, f *settings.Flow) error {
f.UI.SetCSRF(s.d.GenerateCSRFToken(r))
f.UI.Nodes.Upsert(NewPasswordNode("password", node.InputAttributeAutocompleteNewPassword).WithMetaLabel(text.NewInfoNodeInputPassword()))
f.UI.Nodes.Upsert(NewPasswordNode("password", node.InputAttributeAutocompleteNewPassword, s.d.Config().PasswordPolicyConfig(r.Context())).WithMetaLabel(text.NewInfoNodeInputPassword()))
f.UI.Nodes.Append(node.NewInputField("method", "password", node.PasswordGroup, node.InputAttributeTypeSubmit).WithMetaLabel(text.NewInfoNodeLabelSave()))

return nil
Expand Down
4 changes: 4 additions & 0 deletions selfservice/strategy/password/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ func (s *DefaultPasswordValidator) validate(ctx context.Context, identifier, pas
return errors.Errorf("password length must be at least %d characters but only got %d", passwordPolicyConfig.MinPasswordLength, len(password))
}

if len(password) > int(passwordPolicyConfig.MaxPasswordLength) {
return errors.Errorf("password length cannot exceed %d characters", passwordPolicyConfig.MaxPasswordLength)
}

if passwordPolicyConfig.IdentifierSimilarityCheckEnabled && len(identifier) > 0 {
compIdentifier, compPassword := strings.ToLower(identifier), strings.ToLower(password)
dist := levenshtein.Distance(compIdentifier, compPassword)
Expand Down
5 changes: 5 additions & 0 deletions test/e2e/cypress/support/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ export type IgnoreLookupNetworkErrors = boolean
* Defines the minimum length of the password.
*/
export type MinimumPasswordLength = number
/**
* Defines the maximum length of the password.
*/
export type MaximumPasswordLength = number
/**
* If set to false the password validation does not check for similarity between the password and the user identifier.
*/
Expand Down Expand Up @@ -774,6 +778,7 @@ export interface PasswordConfiguration {
max_breaches?: AllowPasswordBreaches
ignore_network_errors?: IgnoreLookupNetworkErrors
min_password_length?: MinimumPasswordLength
max_password_length?: MaximumPasswordLength
identifier_similarity_check_enabled?: EnablePasswordIdentifierSimilarityCheck
}
export interface TOTPConfiguration {
Expand Down
6 changes: 6 additions & 0 deletions ui/node/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ type InputAttributes struct {
// The autocomplete attribute for the input.
Autocomplete UiNodeInputAttributeAutocomplete `json:"autocomplete,omitempty"`

// The minlength attribute for the input.
MinLength uint `json:"minlength,omitempty"`

// The maxlength attribute for the input.
MaxLength uint `json:"maxlength,omitempty"`

// The input's label text.
Label *text.Message `json:"label,omitempty"`

Expand Down
2 changes: 2 additions & 0 deletions ui/node/fixtures/sort/expected/1.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
"attributes": {
"name": "password",
"type": "password",
"minlength": 8,
"maxlength": 1024,
"required": true,
"disabled": false,
"node_type": "input"
Expand Down
2 changes: 2 additions & 0 deletions ui/node/fixtures/sort/expected/2.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@
"attributes": {
"name": "password",
"type": "password",
"minlength": 8,
"maxlength": 1024,
"required": true,
"disabled": false,
"node_type": "input"
Expand Down
2 changes: 2 additions & 0 deletions ui/node/fixtures/sort/expected/4.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
"attributes": {
"name": "password",
"type": "password",
"minlength": 8,
"maxlength": 1024,
"required": true,
"disabled": false,
"node_type": "input"
Expand Down
2 changes: 2 additions & 0 deletions ui/node/fixtures/sort/input/1.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@
"attributes": {
"name": "password",
"type": "password",
"minlength": 8,
"maxlength": 1024,
"required": true,
"disabled": false
},
Expand Down
2 changes: 2 additions & 0 deletions ui/node/fixtures/sort/input/2.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"attributes": {
"name": "password",
"type": "password",
"minlength": 8,
"maxlength": 1024,
"required": true,
"disabled": false
},
Expand Down
2 changes: 2 additions & 0 deletions ui/node/fixtures/sort/input/4.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
"attributes": {
"disabled": false,
"name": "password",
"minlength": 8,
"maxlength": 1024,
"required": true,
"type": "password"
},
Expand Down

0 comments on commit 94e23d3

Please sign in to comment.