Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added strict validation for username and password in backend. #4670

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions chaoscenter/authentication/api/docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,12 @@ const docTemplate = `{
"$ref": "#/definitions/response.ErrInvalidRequest"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/response.ErrStrictUsernamePolicyViolation"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
Expand Down Expand Up @@ -1218,6 +1224,19 @@ const docTemplate = `{
}
}
},
"response.ErrStrictUsernamePolicyViolation": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"example": 401
},
"message": {
"type": "string",
"example": "The username be atleast 3 characters long and atmost 12 characters long."
}
}
},
"response.ErrUnauthorized": {
"type": "object",
"properties": {
Expand Down
19 changes: 19 additions & 0 deletions chaoscenter/authentication/api/docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,12 @@
"$ref": "#/definitions/response.ErrInvalidRequest"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/response.ErrStrictUsernamePolicyViolation"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
Expand Down Expand Up @@ -1208,6 +1214,19 @@
}
}
},
"response.ErrStrictUsernamePolicyViolation": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"example": 401
},
"message": {
"type": "string",
"example": "The username be atleast 3 characters long and atmost 12 characters long."
}
}
},
"response.ErrUnauthorized": {
"type": "object",
"properties": {
Expand Down
14 changes: 14 additions & 0 deletions chaoscenter/authentication/api/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ definitions:
1 lowercase alphabet, 1 uppercase alphabet and 1 special character
type: string
type: object
response.ErrStrictUsernamePolicyViolation:
properties:
code:
example: 401
type: integer
message:
example: The username be atleast 3 characters long and atmost 12 characters
long.
type: string
type: object
response.ErrUnauthorized:
properties:
code:
Expand Down Expand Up @@ -762,6 +772,10 @@ paths:
description: Bad Request
schema:
$ref: '#/definitions/response.ErrInvalidRequest'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.ErrStrictUsernamePolicyViolation'
"500":
description: Internal Server Error
schema:
Expand Down
5 changes: 5 additions & 0 deletions chaoscenter/authentication/api/handlers/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ type ErrStrictPasswordPolicyViolation struct {
Message string `json:"message" example:"Please ensure the password is 8 characters long and has 1 digit, 1 lowercase alphabet, 1 uppercase alphabet and 1 special character"`
}

type ErrStrictUsernamePolicyViolation struct {
Code int `json:"code" example:"401"`
Message string `json:"message" example:"The username be atleast 3 characters long and atmost 12 characters long."`
}

type ErrEmptyProjectName struct {
Code int `json:"code" example:"400"`
Message string `json:"message" example:"Project name can't be empty"`
Expand Down
39 changes: 35 additions & 4 deletions chaoscenter/authentication/api/handlers/rest/user_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const BearerSchema = "Bearer "
// @Failure 400 {object} response.ErrInvalidRequest
// @Failure 401 {object} response.ErrUnauthorized
// @Failure 400 {object} response.ErrInvalidEmail
// @Failure 401 {object} response.ErrStrictPasswordPolicyViolation
// @Failure 401 {object} response.ErrStrictUsernamePolicyViolation
// @Failure 401 {object} response.ErrUserExists
// @Failure 500 {object} response.ErrServerError
// @Success 200 {object} response.UserResponse{}
Expand Down Expand Up @@ -57,6 +59,20 @@ func CreateUser(service services.ApplicationService) gin.HandlerFunc {
c.JSON(utils.ErrorStatusCodes[utils.ErrInvalidRequest], presenter.CreateErrorResponse(utils.ErrInvalidRequest))
return
}
//username validation
err = utils.ValidateStrictUsername(userRequest.Username)
if err != nil {
c.JSON(utils.ErrorStatusCodes[utils.ErrStrictUsernamePolicyViolation], presenter.CreateErrorResponse(utils.ErrStrictUsernamePolicyViolation))
return
}

// password validation
err = utils.ValidateStrictPassword(userRequest.Password)
aryan-bhokare marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
c.JSON(utils.ErrorStatusCodes[utils.ErrStrictPasswordPolicyViolation], presenter.CreateErrorResponse(utils.ErrStrictPasswordPolicyViolation))
return
}


// Assigning UID to user
uID := uuid.Must(uuid.NewRandom()).String()
Expand Down Expand Up @@ -105,6 +121,8 @@ func CreateUser(service services.ApplicationService) gin.HandlerFunc {
// @Accept json
// @Produce json
// @Failure 400 {object} response.ErrInvalidRequest
// @Failure 401 {object} response.ErrStrictPasswordPolicyViolation
// @Failure 401 {object} response.ErrStrictUsernamePolicyViolation
// @Failure 500 {object} response.ErrServerError
// @Success 200 {object} response.MessageResponse{}
// @Router /update/details [post]
Expand All @@ -123,13 +141,26 @@ func UpdateUser(service services.ApplicationService) gin.HandlerFunc {

// Checking if password is updated
if userRequest.Password != "" {
err := utils.ValidateStrictPassword(userRequest.Password)
if err != nil {
c.JSON(utils.ErrorStatusCodes[utils.ErrStrictPasswordPolicyViolation], presenter.CreateErrorResponse(utils.ErrStrictPasswordPolicyViolation))
return
}
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(userRequest.Password), utils.PasswordEncryptionCost)
if err != nil {
return
}
userRequest.Password = string(hashedPassword)
}

if userRequest.Name != "" {
err = utils.ValidateStrictUsername(userRequest.Name)
aryan-bhokare marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
c.JSON(utils.ErrorStatusCodes[utils.ErrStrictUsernamePolicyViolation], presenter.CreateErrorResponse(utils.ErrStrictUsernamePolicyViolation))
return
}
}

err = service.UpdateUser(&userRequest)
if err != nil {
c.JSON(utils.ErrorStatusCodes[utils.ErrServerError], presenter.CreateErrorResponse(utils.ErrServerError))
Expand Down Expand Up @@ -405,17 +436,17 @@ func UpdatePassword(service services.ApplicationService) gin.HandlerFunc {
}
username := c.MustGet("username").(string)
userPasswordRequest.Username = username
if utils.StrictPasswordPolicy {
if userPasswordRequest.NewPassword != "" {
err := utils.ValidateStrictPassword(userPasswordRequest.NewPassword)
if err != nil {
c.JSON(utils.ErrorStatusCodes[utils.ErrStrictPasswordPolicyViolation], presenter.CreateErrorResponse(utils.ErrStrictPasswordPolicyViolation))
return
}
}
if userPasswordRequest.NewPassword == "" {
}else {
c.JSON(utils.ErrorStatusCodes[utils.ErrInvalidRequest], presenter.CreateErrorResponse(utils.ErrInvalidRequest))
return
}

err = service.UpdatePassword(&userPasswordRequest, true)
if err != nil {
log.Info(err)
Expand Down Expand Up @@ -460,7 +491,7 @@ func ResetPassword(service services.ApplicationService) gin.HandlerFunc {
var adminUser entities.User
adminUser.Username = c.MustGet("username").(string)
adminUser.ID = uid
if utils.StrictPasswordPolicy {
if userPasswordRequest.NewPassword != "" {
err := utils.ValidateStrictPassword(userPasswordRequest.NewPassword)
if err != nil {
c.JSON(utils.ErrorStatusCodes[utils.ErrStrictPasswordPolicyViolation], presenter.CreateErrorResponse(utils.ErrStrictPasswordPolicyViolation))
Expand Down
3 changes: 3 additions & 0 deletions chaoscenter/authentication/pkg/utils/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var (
ErrServerError AppError = errors.New("server_error")
ErrInvalidRequest AppError = errors.New("invalid_request")
ErrStrictPasswordPolicyViolation AppError = errors.New("password_policy_violation")
ErrStrictUsernamePolicyViolation AppError = errors.New("username_policy_violation")
ErrUnauthorized AppError = errors.New("unauthorized")
ErrUserExists AppError = errors.New("user_exists")
ErrUserNotFound AppError = errors.New("user does not exist")
Expand All @@ -31,6 +32,7 @@ var ErrorStatusCodes = map[AppError]int{
ErrUnauthorized: 401,
ErrUserExists: 401,
ErrStrictPasswordPolicyViolation: 401,
ErrStrictUsernamePolicyViolation: 401,
ErrUserNotFound: 400,
ErrProjectNotFound: 400,
ErrUpdatingAdmin: 400,
Expand All @@ -49,6 +51,7 @@ var ErrorDescriptions = map[AppError]string{
ErrUnauthorized: "The user does not have requested authorization to access this resource",
ErrUserExists: "This username is already assigned to another user",
ErrStrictPasswordPolicyViolation: "Please ensure the password is 8 characters long and has 1 digit, 1 lowercase alphabet, 1 uppercase alphabet and 1 special character",
ErrStrictUsernamePolicyViolation: "The username be atleast 3 characters long and atmost 12 characters long.",
aryan-bhokare marked this conversation as resolved.
Show resolved Hide resolved
ErrEmptyProjectName: "Project name can't be empty",
ErrInvalidRole: "Role is invalid",
ErrProjectNotFound: "This project does not exist",
Expand Down
17 changes: 17 additions & 0 deletions chaoscenter/authentication/pkg/utils/sanitizers.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,20 @@ func ValidateStrictPassword(input string) error {
}
return nil
}

func ValidateStrictUsername(username string) error {
if len(username) < 3 {
return fmt.Errorf("username must be at least three characters long")
}

if len(username) > 16 {
return fmt.Errorf("username must be at most sixteen characters long")
}

// Ensure username doesn't contain special characters (only letters, numbers, and underscores are allowed)
if matched, _ := regexp.MatchString(`^[a-zA-Z0-9_]+$`, username); !matched {
aryan-bhokare marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("username can only contain letters, numbers, and underscores")
}

return nil
}
Loading