Auth: Enhance password validation.
Increase minimum length to 20.
Check for digits, lower/upper case and special characters.
Change-Id: I7837780716487843f01ed2af97fcf30505d27ef7
diff --git a/core/auth/ui/api.go b/core/auth/ui/api.go
index ab0ea76..6fb7426 100644
--- a/core/auth/ui/api.go
+++ b/core/auth/ui/api.go
@@ -5,6 +5,8 @@
"encoding/json"
"fmt"
"net/http"
+ "strings"
+ "unicode"
"github.com/gorilla/mux"
)
@@ -37,22 +39,20 @@
return s.serv.ListenAndServe()
}
-const identityCreateTmpl = `
-{
- "credentials": {
- "password": {
- "config": {
- "password": "%s"
- }
- }
- },
- "schema_id": "user",
- "state": "active",
- "traits": {
- "username": "%s"
- }
+type kratosIdentityCreateReq struct {
+ Credentials struct {
+ Password struct {
+ Config struct {
+ Password string `json:"password"`
+ } `json:"config"`
+ } `json:"password"`
+ } `json:"credentials"`
+ SchemaID string `json:"schema_id"`
+ State string `json:"state"`
+ Traits struct {
+ Username string `json:"username"`
+ } `json:"traits"`
}
-`
type identityCreateReq struct {
Username string `json:"username,omitempty"`
@@ -92,8 +92,26 @@
func validatePassword(password string) []ValidationError {
var errors []ValidationError
- if len(password) < 6 {
- errors = append(errors, ValidationError{"password", "Password must be at least 6 characters long."})
+ if len(password) < 20 {
+ errors = append(errors, ValidationError{"password", "Password must be at least 20 characters long."})
+ }
+ digit := false
+ lowerCase := false
+ upperCase := false
+ special := false
+ for _, c := range password {
+ if unicode.IsDigit(c) {
+ digit = true
+ } else if unicode.IsLower(c) {
+ lowerCase = true
+ } else if unicode.IsUpper(c) {
+ upperCase = true
+ } else if strings.Contains(" !\"#$%&'()*+,-./:;<=>?@[\\]^_{|}~", string(c)) {
+ special = true
+ }
+ }
+ if !digit || !lowerCase || !upperCase || !special {
+ errors = append(errors, ValidationError{"password", "Password must contain at least one ditig, lower/upper and special character"})
}
// TODO other validations
return errors
@@ -122,8 +140,16 @@
replyWithErrors(w, allErrors)
return
}
+ var kreq kratosIdentityCreateReq
+ kreq.Credentials.Password.Config.Password = req.Password
+ kreq.SchemaID = "user"
+ kreq.State = "active"
+ kreq.Traits.Username = req.Username
var buf bytes.Buffer
- fmt.Fprintf(&buf, identityCreateTmpl, req.Password, req.Username)
+ if err := json.NewEncoder(&buf).Encode(kreq); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
resp, err := http.Post(s.identitiesEndpoint(), "application/json", &buf)
if err != nil {
http.Error(w, "failed", http.StatusInternalServerError)
diff --git a/core/auth/ui/api_test.go b/core/auth/ui/api_test.go
new file mode 100644
index 0000000..90e64be
--- /dev/null
+++ b/core/auth/ui/api_test.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+ "testing"
+)
+
+func TestPasswordInvalid(t *testing.T) {
+ errs := validatePassword("foobar")
+ if len(errs) != 2 {
+ t.Fatal(errs)
+ }
+}
+
+func TestPasswordValid(t *testing.T) {
+ errs := validatePassword("foBa2r-gdkjS1-SA0120")
+ if len(errs) != 0 {
+ t.Fatal(errs)
+ }
+}
diff --git a/core/auth/ui/go.mod b/core/auth/ui/go.mod
index 49c33b1..0930937 100644
--- a/core/auth/ui/go.mod
+++ b/core/auth/ui/go.mod
@@ -1,8 +1,19 @@
module github.com/giolekva/pcloud/core/auth/ui
-go 1.16
+go 1.20
require (
github.com/gorilla/mux v1.8.0
github.com/itaysk/regogo v0.0.0-20200423164851-e9433c1fe5a7
)
+
+require (
+ github.com/OneOfOne/xxhash v1.2.7 // indirect
+ github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4 // indirect
+ github.com/gobwas/glob v0.2.3 // indirect
+ github.com/open-policy-agent/opa v0.18.0 // indirect
+ github.com/pkg/errors v0.0.0-20181023235946-059132a15dd0 // indirect
+ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a // indirect
+ github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b // indirect
+ gopkg.in/yaml.v2 v2.2.1 // indirect
+)