fix(auth): support login with email in addition to username
This commit is contained in:
parent
73ad7296ca
commit
51a8293a11
3 changed files with 17 additions and 6 deletions
|
|
@ -47,7 +47,8 @@ type registerCompanyTarget struct {
|
|||
}
|
||||
|
||||
type loginRequest struct {
|
||||
Username string `json:"username"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,12 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
|
|||
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 {
|
||||
writeError(w, http.StatusUnauthorized, err)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -604,11 +604,16 @@ func (s *Service) RegisterAccount(ctx context.Context, company *domain.Company,
|
|||
}
|
||||
|
||||
// Authenticate validates credentials and emits a signed JWT.
|
||||
func (s *Service) Authenticate(ctx context.Context, username, password string) (string, time.Time, error) {
|
||||
user, err := s.repo.GetUserByUsername(ctx, username)
|
||||
func (s *Service) Authenticate(ctx context.Context, identifier, password string) (string, time.Time, error) {
|
||||
// Try fetching by username first
|
||||
user, err := s.repo.GetUserByUsername(ctx, identifier)
|
||||
if err != nil {
|
||||
// Return generic error to avoid leaking DB details or user existence
|
||||
return "", time.Time{}, errors.New("invalid credentials")
|
||||
// Try fetching by email
|
||||
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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue