Implement support for base password constraints

This commit is contained in:
Tomaž Jerman
2021-11-22 13:36:32 +01:00
parent edbbf2f01b
commit 420b5ee195
21 changed files with 98 additions and 30 deletions
+7
View File
@@ -491,6 +491,7 @@ func (app *CortezaApp) Activate(ctx context.Context) (err error) {
updateFederationSettings(app.Opt.Federation, sysService.CurrentSettings)
updateAuthSettings(app.AuthService, sysService.CurrentSettings)
updatePasswdSettings(app.Opt.Auth, sysService.CurrentSettings)
sysService.DefaultSettings.Register("auth.", func(ctx context.Context, current interface{}, set types.SettingValueSet) {
appSettings, is := current.(*types.AppSettings)
if !is {
@@ -498,6 +499,7 @@ func (app *CortezaApp) Activate(ctx context.Context) (err error) {
}
updateAuthSettings(app.AuthService, appSettings)
updatePasswdSettings(app.Opt.Auth, sysService.CurrentSettings)
})
updateLocaleSettings(app.Opt.Locale)
@@ -601,6 +603,11 @@ func updateFederationSettings(opt options.FederationOpt, current *types.AppSetti
current.Federation.Enabled = opt.Enabled
}
// Checks if password security is enabled in the options
func updatePasswdSettings(opt options.AuthOpt, current *types.AppSettings) {
current.Auth.Internal.PasswordConstraints.PasswordSecurity = opt.PasswordSecurity
}
// Sanitizes application (current) settings with languages from options
//
// It updates resource-translations.languages slice
+1 -1
View File
@@ -73,7 +73,7 @@ func Test_changePasswordProc(t *testing.T) {
},
{
name: "provided password is not secure",
payload: map[string]string{"error": "provided password is not secure; use longer password with more non-alphanumeric character"},
payload: map[string]string{"error": "provided password is not secure; use longer password with more special characters"},
link: GetLinks().ChangePassword,
fn: func(_ *settings.Settings) {
authService = &authServiceMocked{
+1 -1
View File
@@ -147,7 +147,7 @@ func Test_signupProc(t *testing.T) {
err: "",
alerts: []request.Alert(nil),
link: GetLinks().Signup,
payload: map[string]string{"email": "", "error": "provided password is not secure; use longer password with more non-alphanumeric character", "handle": "", "name": ""},
payload: map[string]string{"email": "", "error": "provided password is not secure; use longer password with more special characters", "handle": "", "name": ""},
fn: func(_ *settings.Settings) {
authService = &authServiceMocked{
internalSignUp: func(c context.Context, user *types.User, s string) (u *types.User, err error) {
+2
View File
@@ -15,6 +15,7 @@ import (
type (
AuthOpt struct {
LogEnabled bool `env:"AUTH_LOG_ENABLED"`
PasswordSecurity bool `env:"AUTH_PASSWORD_SECURITY"`
Secret string `env:"AUTH_JWT_SECRET"`
AccessTokenLifetime time.Duration `env:"AUTH_OAUTH2_ACCESS_TOKEN_LIFETIME"`
RefreshTokenLifetime time.Duration `env:"AUTH_OAUTH2_REFRESH_TOKEN_LIFETIME"`
@@ -44,6 +45,7 @@ type (
// Auth initializes and returns a AuthOpt with default values
func Auth() (o *AuthOpt) {
o = &AuthOpt{
PasswordSecurity: true,
Secret: getSecretFromEnv("jwt secret"),
AccessTokenLifetime: time.Hour * 2,
RefreshTokenLifetime: time.Hour * 24 * 3,
+11
View File
@@ -10,6 +10,17 @@ props:
description: |-
Enable extra logging for authentication flows
- name: passwordSecurity
type: bool
default: true
description: |-
Password security allows you to disable constraints to which passwords must conform to.
[CAUTION]
====
Password security should not be disabled on production environments as it is insecure.
====
- name: secret
env: AUTH_JWT_SECRET
default: getSecretFromEnv("jwt secret")
+33 -1
View File
@@ -3,6 +3,7 @@ package service
import (
"context"
"fmt"
"math"
rand2 "math/rand"
"regexp"
"strconv"
@@ -59,6 +60,9 @@ const (
credentialsTypeMFAEmailOTP = "mfa-email-otp"
credentialsTokenLength = 32
passwordMinLength = 8
passwordMaxLength = 256
)
var (
@@ -622,10 +626,38 @@ func (svc auth) hashPassword(password string) (hash []byte, err error) {
}
func (svc auth) CheckPasswordStrength(password string) bool {
if len(password) <= 4 {
pwdL := len(password)
// Ignore defined password constraints
if !svc.settings.Auth.Internal.PasswordConstraints.PasswordSecurity {
return true
}
// Check the password length
minL := math.Max(float64(passwordMinLength), float64(svc.settings.Auth.Internal.PasswordConstraints.MinLength))
if pwdL < int(minL) || pwdL > passwordMaxLength {
return false
}
// Check special constraints
// - numeric characters
count := svc.settings.Auth.Internal.PasswordConstraints.MinNumCount
if count > 0 {
rr := regexp.MustCompile("[0-9]")
if uint(len(rr.FindAllStringIndex(password, -1))) < count {
return false
}
}
// - special characters
count = svc.settings.Auth.Internal.PasswordConstraints.MinSpecialCount
if count > 0 {
rr := regexp.MustCompile("[^0-9a-zA-Z]")
if uint(len(rr.FindAllStringIndex(password, -1))) < count {
return false
}
}
return true
}
+4 -3
View File
@@ -11,12 +11,13 @@ package service
import (
"context"
"fmt"
"strings"
"time"
"github.com/cortezaproject/corteza-server/pkg/actionlog"
"github.com/cortezaproject/corteza-server/pkg/errors"
"github.com/cortezaproject/corteza-server/pkg/locale"
"github.com/cortezaproject/corteza-server/system/types"
"strings"
"time"
)
type (
@@ -1248,7 +1249,7 @@ func AuthErrPasswordNotSecure(mm ...*authActionProps) *errors.Error {
var e = errors.New(
errors.KindInternal,
p.Format("provided password is not secure; use longer password with more non-alphanumeric character", nil),
p.Format("provided password is not secure; use longer password with more special characters", nil),
errors.Meta("type", "passwordNotSecure"),
errors.Meta("resource", "system:auth"),
+1 -1
View File
@@ -143,7 +143,7 @@ errors:
message: "password create is disabled"
- error: passwordNotSecure
message: "provided password is not secure; use longer password with more non-alphanumeric character"
message: "provided password is not secure; use longer password with more special characters"
- error: externalDisabledByConfig
message: "external authentication (using external authentication provider) is disabled"
+4 -3
View File
@@ -11,12 +11,13 @@ package service
import (
"context"
"fmt"
"strings"
"time"
"github.com/cortezaproject/corteza-server/pkg/actionlog"
"github.com/cortezaproject/corteza-server/pkg/errors"
"github.com/cortezaproject/corteza-server/pkg/locale"
"github.com/cortezaproject/corteza-server/system/types"
"strings"
"time"
)
type (
@@ -1261,7 +1262,7 @@ func UserErrPasswordNotSecure(mm ...*userActionProps) *errors.Error {
var e = errors.New(
errors.KindInternal,
p.Format("provided password is not secure; use longer password with more non-alphanumeric character", nil),
p.Format("provided password is not secure; use longer password with more special characters", nil),
errors.Meta("type", "passwordNotSecure"),
errors.Meta("resource", "system:user"),
+1 -1
View File
@@ -145,7 +145,7 @@ errors:
severity: warning
- error: passwordNotSecure
message: "provided password is not secure; use longer password with more non-alphanumeric character"
message: "provided password is not secure; use longer password with more special characters"
- error: maxUserLimitReached
message: "you have reached your user limit, contact your Corteza administrator"
+23 -9
View File
@@ -41,7 +41,7 @@ type (
Auth struct {
Internal struct {
// Is internal authentication (username + password) enabled
Enabled bool
Enabled bool `json:"-"`
Signup struct {
// Can users register
@@ -49,10 +49,10 @@ type (
// Users must confirm their emails when signing-up
EmailConfirmationRequired bool `kv:"email-confirmation-required"`
}
} `json:"-"`
// Can users reset their passwords
PasswordReset struct{ Enabled bool } `kv:"password-reset"`
PasswordReset struct{ Enabled bool } `json:"-" kv:"password-reset"`
// PasswordCreate setting for create password for user via generated link with token
// If user has no password then link redirects to create password page
@@ -61,14 +61,28 @@ type (
PasswordCreate struct {
Enabled bool
Expires uint
} `kv:"password-create"`
} `json:"-" kv:"password-create"`
// Splits credentials check into 2 parts
// If user has password credentials it offers him to enter the password
// Otherwise we offer the user to choose among the enabled external providers
// If only one ext. provider is enabled, user is automatically redirected there
SplitCredentialsCheck bool `kv:"split-credentials-check"`
}
SplitCredentialsCheck bool `json:"-" kv:"split-credentials-check"`
PasswordConstraints struct {
// Should the environment not enforce the constraints
PasswordSecurity bool `kv:"-" json:"passwordSecurity"`
// The min password length
MinLength uint `kv:"min-length"`
// The min number of numeric characters
MinNumCount uint `kv:"min-num-count"`
// The min number of special characters
MinSpecialCount uint `kv:"min-special-count"`
} `kv:"password-constraints" json:"passwordConstraints"`
} `json:"internal"`
External struct {
// Is external authentication
@@ -100,7 +114,7 @@ type (
// all external providers we know
Providers ExternalAuthProviderSet
}
} `json:"-"`
MultiFactor struct {
EmailOTP struct {
@@ -129,13 +143,13 @@ type (
// TOTP issuer, defaults to "Corteza"
Issuer string
} `kv:"totp"`
} `kv:"multi-factor"`
} `json:"-" kv:"multi-factor"`
Mail struct {
FromAddress string `kv:"from-address"`
FromName string `kv:"from-name"`
} `json:"-"`
} `json:"-"`
} `json:"auth"`
Compose struct {
// UI related settings
@@ -19,7 +19,7 @@ errors:
notAllowedToRemoveTOTP: not allowed to remove TOTP
passwodResetFailedOldPasswordCheckFailed: failed to change password, old password does not match
passwordChangeFailedForUnknownUser: failed to change password for the unknown user
passwordNotSecure: provided password is not secure; use longer password with more non-alphanumeric character
passwordNotSecure: provided password is not secure; use longer password with more special characters
passwordResetDisabledByConfig: password reset is disabled
profileWithoutValidEmail: external authentication provider returned profile without valid email
unconfiguredTOTP: TOTP not configured
@@ -16,5 +16,5 @@ errors:
notAllowedToUpdate: not allowed to update this user
notAllowedToUpdateSystem: not allowed to update system users
notFound: user not found
passwordNotSecure: provided password is not secure; use longer password with more non-alphanumeric character
passwordNotSecure: provided password is not secure; use longer password with more special characters
usernameNotUnique: username not unique
@@ -20,7 +20,7 @@ errors:
notAllowedToRemoveTOTP: not allowed to remove TOTP
passwodResetFailedOldPasswordCheckFailed: failed to change password, old password does not match
passwordChangeFailedForUnknownUser: failed to change password for the unknown user
passwordNotSecure: provided password is not secure; use longer password with more non-alphanumeric character
passwordNotSecure: provided password is not secure; use longer password with more special characters
passwordResetDisabledByConfig: password reset is disabled
profileWithoutValidEmail: external authentication provider returned profile without valid email
unconfiguredTOTP: TOTP not configured
@@ -17,5 +17,5 @@ errors:
notAllowedToUpdate: not allowed to update this user
notAllowedToUpdateSystem: not allowed to update system users
notFound: user not found
passwordNotSecure: provided password is not secure; use longer password with more non-alphanumeric character
passwordNotSecure: provided password is not secure; use longer password with more special characters
usernameNotUnique: username not unique
@@ -20,7 +20,7 @@ errors:
notAllowedToRemoveTOTP: not allowed to remove TOTP
passwodResetFailedOldPasswordCheckFailed: failed to change password, old password does not match
passwordChangeFailedForUnknownUser: failed to change password for the unknown user
passwordNotSecure: provided password is not secure; use longer password with more non-alphanumeric character
passwordNotSecure: provided password is not secure; use longer password with more special characters
passwordResetDisabledByConfig: password reset is disabled
profileWithoutValidEmail: external authentication provider returned profile without valid email
unconfiguredTOTP: TOTP not configured
@@ -17,5 +17,5 @@ errors:
notAllowedToUpdate: not allowed to update this user
notAllowedToUpdateSystem: not allowed to update system users
notFound: user not found
passwordNotSecure: provided password is not secure; use longer password with more non-alphanumeric character
passwordNotSecure: provided password is not secure; use longer password with more special characters
usernameNotUnique: username not unique
@@ -20,7 +20,7 @@ errors:
notAllowedToRemoveTOTP: not allowed to remove TOTP
passwodResetFailedOldPasswordCheckFailed: failed to change password, old password does not match
passwordChangeFailedForUnknownUser: failed to change password for the unknown user
passwordNotSecure: provided password is not secure; use longer password with more non-alphanumeric character
passwordNotSecure: provided password is not secure; use longer password with more special characters
passwordResetDisabledByConfig: password reset is disabled
profileWithoutValidEmail: external authentication provider returned profile without valid email
unconfiguredTOTP: TOTP not configured
@@ -17,5 +17,5 @@ errors:
notAllowedToUpdate: not allowed to update this user
notAllowedToUpdateSystem: not allowed to update system users
notFound: user not found
passwordNotSecure: provided password is not secure; use longer password with more non-alphanumeric character
passwordNotSecure: provided password is not secure; use longer password with more special characters
usernameNotUnique: username not unique
@@ -20,7 +20,7 @@ errors:
notAllowedToRemoveTOTP: not allowed to remove TOTP
passwodResetFailedOldPasswordCheckFailed: failed to change password, old password does not match
passwordChangeFailedForUnknownUser: failed to change password for the unknown user
passwordNotSecure: provided password is not secure; use longer password with more non-alphanumeric character
passwordNotSecure: provided password is not secure; use longer password with more special characters
passwordResetDisabledByConfig: password reset is disabled
profileWithoutValidEmail: external authentication provider returned profile without valid email
unconfiguredTOTP: TOTP not configured
@@ -17,5 +17,5 @@ errors:
notAllowedToUpdate: not allowed to update this user
notAllowedToUpdateSystem: not allowed to update system users
notFound: user not found
passwordNotSecure: provided password is not secure; use longer password with more non-alphanumeric character
passwordNotSecure: provided password is not secure; use longer password with more special characters
usernameNotUnique: username not unique