fix(auth): support login with email in addition to username

This commit is contained in:
Tiago Yamamoto 2025-12-26 17:05:12 -03:00
parent 73ad7296ca
commit 51a8293a11
3 changed files with 17 additions and 6 deletions

View file

@ -47,7 +47,8 @@ type registerCompanyTarget struct {
} }
type loginRequest struct { type loginRequest struct {
Username string `json:"username"` Username string `json:"username,omitempty"`
Email string `json:"email,omitempty"`
Password string `json:"password"` Password string `json:"password"`
} }

View file

@ -106,7 +106,12 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
return return
} }
token, exp, err := h.svc.Authenticate(r.Context(), req.Username, req.Password) identifier := req.Email
if identifier == "" {
identifier = req.Username
}
token, exp, err := h.svc.Authenticate(r.Context(), identifier, req.Password)
if err != nil { if err != nil {
writeError(w, http.StatusUnauthorized, err) writeError(w, http.StatusUnauthorized, err)
return return

View file

@ -604,11 +604,16 @@ func (s *Service) RegisterAccount(ctx context.Context, company *domain.Company,
} }
// Authenticate validates credentials and emits a signed JWT. // Authenticate validates credentials and emits a signed JWT.
func (s *Service) Authenticate(ctx context.Context, username, password string) (string, time.Time, error) { func (s *Service) Authenticate(ctx context.Context, identifier, password string) (string, time.Time, error) {
user, err := s.repo.GetUserByUsername(ctx, username) // Try fetching by username first
user, err := s.repo.GetUserByUsername(ctx, identifier)
if err != nil { if err != nil {
// Return generic error to avoid leaking DB details or user existence // Try fetching by email
return "", time.Time{}, errors.New("invalid credentials") user, err = s.repo.GetUserByEmail(ctx, identifier)
if err != nil {
// Return generic error to avoid leaking DB details or user existence
return "", time.Time{}, errors.New("invalid credentials")
}
} }
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(s.pepperPassword(password))); err != nil { if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(s.pepperPassword(password))); err != nil {