github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/pkg/jwt/basic/password_verifier.go (about)

     1  package basic
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  )
     9  
    10  const (
    11  	contentTypeJSON string = "application/json"
    12  )
    13  
    14  // user represents a user that wants to login
    15  type user struct {
    16  	Username string `json:"username"`
    17  	Password string `json:"password"`
    18  }
    19  
    20  // Equals compares one user to another
    21  func (u *user) Equals(user *user) bool {
    22  	return user.Username == u.Username && user.Password == u.Password
    23  }
    24  
    25  // PasswordVerifier checks if the current user `matches any of the given passwords
    26  type PasswordVerifier struct {
    27  	users []*user
    28  }
    29  
    30  // NewPasswordVerifier creates a new instance of PasswordVerifier
    31  func NewPasswordVerifier(users []*user) *PasswordVerifier {
    32  	return &PasswordVerifier{users}
    33  }
    34  
    35  // Verify makes a check and return a boolean if the check was successful or not
    36  func (v *PasswordVerifier) Verify(r *http.Request, httpClient *http.Client) (bool, error) {
    37  	currentUser, err := v.getUserFromRequest(r)
    38  	if err != nil {
    39  		return false, fmt.Errorf("could not get user from request: %w", err)
    40  	}
    41  
    42  	for _, user := range v.users {
    43  		if user.Equals(currentUser) {
    44  			return true, nil
    45  		}
    46  	}
    47  
    48  	return false, errors.New("incorrect username or password")
    49  }
    50  
    51  func (v *PasswordVerifier) getUserFromRequest(r *http.Request) (*user, error) {
    52  	var u *user
    53  
    54  	// checks basic auth
    55  	username, password, ok := r.BasicAuth()
    56  	u = &user{
    57  		Username: username,
    58  		Password: password,
    59  	}
    60  
    61  	// checks if the content is json otherwise just get from the form params
    62  	if !ok {
    63  		contentType := filterFlags(r.Header.Get("Content-Type"))
    64  		switch contentType {
    65  		case contentTypeJSON:
    66  			err := json.NewDecoder(r.Body).Decode(&u)
    67  			if err != nil {
    68  				return u, fmt.Errorf("could not parse the json body: %w", err)
    69  			}
    70  		default:
    71  			r.ParseForm()
    72  
    73  			u = &user{
    74  				Username: r.Form.Get("username"),
    75  				Password: r.Form.Get("password"),
    76  			}
    77  		}
    78  	}
    79  
    80  	return u, nil
    81  }
    82  
    83  func filterFlags(content string) string {
    84  	for i, char := range content {
    85  		if char == ' ' || char == ';' {
    86  			return content[:i]
    87  		}
    88  	}
    89  	return content
    90  }