Skip to content

Commit

Permalink
fix: added validation check for user credentials (#228)
Browse files Browse the repository at this point in the history
* fix: added validation check for user credentials

* fix: added error code and more info in validate credentials

* fix: added inline comments
  • Loading branch information
tiwarishubham635 committed Feb 9, 2024
1 parent 2fcaed4 commit e6a8445
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 2 deletions.
36 changes: 34 additions & 2 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ import (
"github.com/twilio/twilio-go/client/form"
)

var alphanumericRegex *regexp.Regexp
var delimitingRegex *regexp.Regexp

func init() {
alphanumericRegex = regexp.MustCompile(`^[a-zA-Z0-9]*$`)
delimitingRegex = regexp.MustCompile(`\.\d+`)
}

// Credentials store user authentication credentials.
type Credentials struct {
Username string
Expand Down Expand Up @@ -87,6 +95,26 @@ func (c *Client) doWithErr(req *http.Request) (*http.Response, error) {
return res, nil
}

// throws error if username and password contains special characters
func (c *Client) validateCredentials() error {
username, password := c.basicAuth()
if !alphanumericRegex.MatchString(username) {
return &TwilioRestError{
Status: 400,
Code: 21222,
Message: "Invalid Username. Illegal chars",
MoreInfo: "https://www.twilio.com/docs/errors/21222"}
}
if !alphanumericRegex.MatchString(password) {
return &TwilioRestError{
Status: 400,
Code: 21224,
Message: "Invalid Password. Illegal chars",
MoreInfo: "https://www.twilio.com/docs/errors/21224"}
}
return nil
}

// SendRequest verifies, constructs, and authorizes an HTTP request.
func (c *Client) SendRequest(method string, rawURL string, data url.Values,
headers map[string]interface{}) (*http.Response, error) {
Expand All @@ -101,8 +129,7 @@ func (c *Client) SendRequest(method string, rawURL string, data url.Values,
if method == http.MethodGet {
if data != nil {
v, _ := form.EncodeToStringWith(data, delimiter, escapee, keepZeros)
regex := regexp.MustCompile(`\.\d+`)
s := regex.ReplaceAllString(v, "")
s := delimitingRegex.ReplaceAllString(v, "")

u.RawQuery = s
}
Expand All @@ -112,6 +139,11 @@ func (c *Client) SendRequest(method string, rawURL string, data url.Values,
valueReader = strings.NewReader(data.Encode())
}

credErr := c.validateCredentials()
if credErr != nil {
return nil, credErr
}

req, err := http.NewRequest(method, u.String(), valueReader)
if err != nil {
return nil, err
Expand Down
22 changes: 22 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,28 @@ func TestClient_SendRequestErrorWithDetails(t *testing.T) {
assert.Equal(t, details, twilioError.Details)
}

func TestClient_SendRequestUsernameError(t *testing.T) {
newTestClient := NewClient("user1\nuser2", "pass")
resp, err := newTestClient.SendRequest("GET", "http://example.org", nil, nil) //nolint:bodyclose
twilioError := err.(*twilio.TwilioRestError)
assert.Nil(t, resp)
assert.Equal(t, 400, twilioError.Status)
assert.Equal(t, 21222, twilioError.Code)
assert.Equal(t, "https://www.twilio.com/docs/errors/21222", twilioError.MoreInfo)
assert.Equal(t, "Invalid Username. Illegal chars", twilioError.Message)
}

func TestClient_SendRequestPasswordError(t *testing.T) {
newTestClient := NewClient("user1", "pass1\npass2")
resp, err := newTestClient.SendRequest("GET", "http://example.org", nil, nil) //nolint:bodyclose
twilioError := err.(*twilio.TwilioRestError)
assert.Nil(t, resp)
assert.Equal(t, 400, twilioError.Status)
assert.Equal(t, 21224, twilioError.Code)
assert.Equal(t, "https://www.twilio.com/docs/errors/21224", twilioError.MoreInfo)
assert.Equal(t, "Invalid Password. Illegal chars", twilioError.Message)
}

func TestClient_SendRequestWithRedirect(t *testing.T) {
redirectServer := httptest.NewServer(http.HandlerFunc(
func(writer http.ResponseWriter, request *http.Request) {
Expand Down

0 comments on commit e6a8445

Please sign in to comment.