fix(auth): restrict max password length to 72 bytes
Bcrypt allows a maximum of 72 bytes. This is part of the algorithm and not something we could change in Vikunja. The solution here was to restrict the password during registration to a max length of 72 bytes. In the future, this should be changed to hash passwords with sha512 or similar before hashing them with bcrypt. Because they should also be salted in that case and the added complexity during the migration phase, this was not implemented yet. The change in this commit only improves the error handling to return an input error instead of a server error when the user enters a password > 72 bytes. Resolves https://vikunja.sentry.io/share/issue/e8e0b64612d84504942feee002ac498a/ (cherry picked from commit 44a43b9f8616f11560c9e04f88f3000a6df5338d)
This commit is contained in:
parent
10edeafa46
commit
ac87035742
@ -7,7 +7,7 @@ export function validatePassword(password: string, validateMinLength: boolean =
|
|||||||
return 'user.auth.passwordNotMin'
|
return 'user.auth.passwordNotMin'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (validateMinLength && password.length > 250) {
|
if (validateMinLength && password.length > 72) {
|
||||||
return 'user.auth.passwordNotMax'
|
return 'user.auth.passwordNotMax'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
"usernameMustNotLookLikeUrl": "The username must not look like a URL.",
|
||||||
"passwordRequired": "Please provide a password.",
|
"passwordRequired": "Please provide a password.",
|
||||||
"passwordNotMin": "Password must have at least 8 characters.",
|
"passwordNotMin": "Password must have at least 8 characters.",
|
||||||
"passwordNotMax": "Password must have at most 250 characters.",
|
"passwordNotMax": "Password must have at most 72 characters.",
|
||||||
"showPassword": "Show the password",
|
"showPassword": "Show the password",
|
||||||
"hidePassword": "Hide the password",
|
"hidePassword": "Hide the password",
|
||||||
"noAccountYet": "Don't have an account yet?",
|
"noAccountYet": "Don't have an account yet?",
|
||||||
|
@ -197,8 +197,8 @@ type APIUserPassword struct {
|
|||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
// The user's username. Cannot contain anything that looks like an url or whitespaces.
|
// The user's username. Cannot contain anything that looks like an url or whitespaces.
|
||||||
Username string `json:"username" valid:"length(3|250),username" minLength:"3" maxLength:"250"`
|
Username string `json:"username" valid:"length(3|250),username" minLength:"3" maxLength:"250"`
|
||||||
// The user's password in clear text. Only used when registering the user.
|
// The user's password in clear text. Only used when registering the user. The maximum limi is 72 bytes, which may be less than 72 characters. This is due to the limit in the bcrypt hashing algorithm used to store passwords in Vikunja.
|
||||||
Password string `json:"password" valid:"length(8|250)" minLength:"8" maxLength:"250"`
|
Password string `json:"password" valid:"bcrypt_password" minLength:"8" maxLength:"72"`
|
||||||
// The user's email address
|
// The user's email address
|
||||||
Email string `json:"email" valid:"email,length(0|250)" maxLength:"250"`
|
Email string `json:"email" valid:"email,length(0|250)" maxLength:"250"`
|
||||||
}
|
}
|
||||||
@ -213,7 +213,7 @@ func (apiUser *APIUserPassword) APIFormat() *User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByID gets informations about a user by its ID
|
// GetUserByID returns user by its ID
|
||||||
func GetUserByID(s *xorm.Session, id int64) (user *User, err error) {
|
func GetUserByID(s *xorm.Session, id int64) (user *User, err error) {
|
||||||
// Apparently xorm does otherwise look for all users but return only one, which leads to returning one even if the ID is 0
|
// Apparently xorm does otherwise look for all users but return only one, which leads to returning one even if the ID is 0
|
||||||
if id < 1 {
|
if id < 1 {
|
||||||
@ -223,7 +223,7 @@ func GetUserByID(s *xorm.Session, id int64) (user *User, err error) {
|
|||||||
return getUser(s, &User{ID: id}, false)
|
return getUser(s, &User{ID: id}, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByUsername gets a user from its user name. This is an extra function to be able to add an extra error check.
|
// GetUserByUsername gets a user from its username. This is an extra function to be able to add an extra error check.
|
||||||
func GetUserByUsername(s *xorm.Session, username string) (user *User, err error) {
|
func GetUserByUsername(s *xorm.Session, username string) (user *User, err error) {
|
||||||
if username == "" {
|
if username == "" {
|
||||||
return &User{}, ErrUserDoesNotExist{}
|
return &User{}, ErrUserDoesNotExist{}
|
||||||
|
@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
package user
|
package user
|
||||||
|
|
||||||
import "github.com/asaskevich/govalidator"
|
import (
|
||||||
|
"github.com/asaskevich/govalidator"
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
govalidator.TagMap["username"] = func(i string) bool {
|
govalidator.TagMap["username"] = func(i string) bool {
|
||||||
@ -33,4 +35,12 @@ func init() {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
govalidator.TagMap["bcrypt_password"] = func(str string) bool {
|
||||||
|
if len(str) < 8 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return len([]byte(str)) < 72
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user